Chúng tôi đang gỡ lỗi sự cố với kết xuất dữ liệu CSV của khách hàng thì chúng tôi gặp phải sự cố. Kết xuất dữ liệu này chứa siêu dữ liệu thư mục và những người làm việc với siêu dữ liệu thư mục sẽ biết, bạn có thể tìm thấy khá nhiều thứ trong đó. ký tự đặc biệt, đánh dấu lạ, html, bạn đặt tên cho nó. Bài đăng này cho bạn biết về một vấn đề mà chúng tôi đã tìm thấy với số cách bạn có thể nói "dòng mới" và một giải pháp thực tế nhanh chóng để giảm thiểu vấn đề đó trong CSV của bạn
Chúng tôi đã ghi dữ liệu của mình ra CSV và hiện đang đọc lại dữ liệu đó và một số dòng bị sai định dạng, bị cắt giữa chừng mà không có lý do rõ ràng
Nhìn vào tệp trong LibreOffice không giúp được gì - nó trông vẫn ổn. Vì vậy, chúng tôi đã chuyển dữ liệu xuống một trong các hàng có vấn đề và xem xét nó trên dòng lệnh python của chúng tôi có thể thấy thủ phạm có thể xảy ra
u'Publications: \u2029A Case Report'
Ẩn mình ở giữa có \u2029
một ký tự unicode mà bạn có thể không quen thuộc. Đó là ký tự cho Dấu phân cách Đoạn văn và không hoàn toàn điên rồ khi tìm thấy điều đó trong tiêu đề bài viết [chúng tôi đã tìm thấy khoảng 10 trên 100.000 tiêu đề trong quá trình này]. Bạn thậm chí có thể thấy ý nghĩa của nó;
ấn phẩm
Một trường hợp nghiên cứu
Chúng tôi đã ghi dữ liệu bằng trình ghi csv python như thế này
f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
Ở đây codec là thư viện python cung cấp cho chúng tôi mã hóa rõ ràng đối với các hoạt động đọc/ghi và là một cách tuyệt vời để đảm bảo bạn đang làm việc với mã hóa phù hợp ngay từ đầu. là trình bao bọc cơ bản cho trình viết csv đảm bảo bạn làm việc với các chuỗi unicode trong ứng dụng của mình. Những điều này cùng nhau tạo thành một cơ sở mạnh mẽ để không phải suy nghĩ lại về unicode hoặc mã hóa bên trong ứng dụng của bạn [chúng giúp bạn tạo ra “chiếc bánh sandwich unicode”]
Tiếp theo, chúng tôi đang đọc dữ liệu như thế này
f = codecs.open[file, "rb", "utf-8"]
reader = UnicodeReader[f]
for row in reader:
# do stuff
[UnicodeReader chỉ là nghịch đảo của UnicodeWriter ở trên, xem cùng một liên kết để biết chi tiết]
Khi xem xét các hàng bên trong vòng lặp, chúng ta sẽ thấy một số hàng chứa nội dung bị cắt bớt và một số chứa phần bị cắt bớt của hàng ở trên. Rõ ràng là nó bị cắt ngắn ở Dấu phân cách Đoạn văn của chúng tôi, nhưng tại sao?
Chà, có rất nhiều cách để nói “dòng mới”. Nếu bạn nghĩ nó chỉ là \n
hoặc
f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
0 thì bạn đã nhầm. \u2029
là một cách nói dòng mới. f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
2 cũng vậy. f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
3 cũng vậy. Trên thực tế, có đủ cách mà chúng tôi đoán rằng thư viện csv đi kèm với python không biết tất cả và thực sự là khôngTrình đọc csv quan tâm đến các dòng mới, nhưng nó hoàn toàn dựa vào hệ điều hành của bạn để xử lý chúng. Nghĩa là, nó chỉ sử dụng
f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
4 để lấy dòng tiếp theo trong tệp của bạn khi đọc nó trong. Và hệ điều hành của bạn thực sự hiểu tất cả các tùy chọn dòng mới và nó sẽ chấm dứt dòng và trả lại ngay khi nó chạm vào một dòngTrình đọc csv đủ thông minh để hiểu rằng dữ liệu trong các ô có thể chứa các dòng mới một cách hợp pháp, nó không chỉ cho rằng chúng ta hoàn thành mỗi khi
f = codecs.open[file, "wb", "utf-8"]
writer = UnicodeWriter[f]
for article in articles:
writer.writerow[[article.id, article.title]]
4 cho nó một dòng. Bởi vì trình đọc là một máy trạng thái, nó biết liệu chúng ta có ở trong một ô hay không và nếu ô có chứa một dòng mới, nó chỉ cần thêm dòng đó vào giá trị của ô. Nó thực hiện điều đó bằng cách tìm kiếm dấu phân cách ở đầu ô. Nếu có, nó sẽ không từ bỏ việc đọc các dòng mới cho đến khi chạm đến dấu phân cách đóng. Tuy nhiên, nếu không có dấu phân cách nào tồn tại, thì dòng mới là thứ nó tìm kiếm để kết thúc ô và hàngVì vậy, nếu CSV của bạn trông như thế này
________số 8_______Trình đọc CSV của bạn sẽ hiểu rằng đây là một hàng. Nhưng nếu nó trông như thế này
cell 1,cell2,a cell\n
with newlines
Nó sẽ hiểu nó là hai
Vấn đề thực sự của chúng tôi là trình soạn thảo csv không phát hiện ra những dòng mới này [nó sẽ nhận được ____14_______ vì điều đó là hiển nhiên, nhưng những cái khác thì không] và theo mặc định, nó không trích dẫn nội dung ô trừ khi nó phát hiện ra một ký tự đặc biệt. Nó sẽ vui vẻ viết ký tự dòng mới của Dấu phân cách đoạn văn của bạn vào tệp trong một chuỗi không được trích dẫn và trình đọc tương đương của bạn sẽ không thể đọc lại hàng đó
Vì vậy, CSV này sẽ hoạt động
article_id,article_title
123456790,"This title has a\u2029 Paragraph separator"
Trong khi điều này sẽ không
article_id,article_title
123456790,This title has a\u2029 Paragraph separator
Vì người viết csv không nhận ra \u2029
là một ký tự xuống dòng, nên nó không bao quanh các dấu ngoặc kép quanh chuỗi giống như nếu nó chứa\n
Cách khắc phục rất dễ dàng, khi xây dựng trình soạn thảo của bạn trong python, bạn nên làm như thế này
writer = UnicodeWriter[f, quoting=csv.QUOTE_ALL]
Điều này đảm bảo rằng các ô csv của bạn TẤT CẢ đều được trích dẫn, do đó, bất kỳ ký tự lạ nào xuất hiện trong đó, bạn sẽ không phá vỡ cấu trúc tệp. Đây thường là một ý tưởng hay ngay cả khi bạn không sử dụng Python
Chỉ có một vài nhược điểm, điều này có thể quan trọng tùy thuộc vào ngữ cảnh của bạn
- Đây không phải là hành vi mặc định đối với người viết csv, vì vậy bạn phải nhớ làm điều đó mỗi khi bạn nghĩ rằng mình sẽ xử lý loại dữ liệu lộn xộn này
- Nó có nghĩa là mọi thứ đều được trích dẫn, làm tăng thêm kích thước không cần thiết cho tệp của bạn
Khi chúng tôi gặp sự cố này, thực sự không có cuộc thảo luận nào về vấn đề này trên bất kỳ diễn đàn nào mà chúng tôi có thể tìm thấy, vì vậy, hy vọng điều này sẽ giúp ích cho bạn nếu bạn gặp phải vấn đề tương tự
Richard là người sáng lập và đối tác cấp cao tại Cottage Labs, một công ty tư vấn phát triển phần mềm chuyên về mọi khía cạnh của vòng đời dữ liệu. Anh ấy thỉnh thoảng trên Twitter tại @richard_d_jones