CSV trong Python thêm một lợi nhuận vận chuyển bổ sung, trên Windows


231
import csv
outfile = file('test.csv', 'w')
writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['hi','dude'])
writer.writerow(['hi2','dude2'])
outfile.close()

Nó tạo ra một tệp, test.csvvới một phần bổ sung \rở mỗi hàng, như vậy:

test.csv

hi,dude\r\r\nhi2,dude2\r\r\n

thay vì mong đợi:

hi,dude\r\nhi2,dude2\r\n

Tại sao điều này xảy ra, hoặc đây thực sự là hành vi mong muốn?

Ghi chú:

  • Hành vi này có thể xảy ra với Python 2 hoặc 3.

Bản sao có thể có của trình soạn thảo CSV 2
John Y

Câu trả lời:


311

Con trăn 3:

  • Theo mô tả của YiboYang , thiết lậpnewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Như đã lưu ý trong các nhận xét của CoDEmanX , hãy đặtnewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Con trăn 2:

Trên Windows, luôn mở các tệp của bạn ở chế độ nhị phân ( "rb"hoặc "wb"), trước khi chuyển chúng đến csv.readerhoặc csv.writer.

Mặc dù tệp là tệp văn bản, CSV được coi là định dạng nhị phân của các thư viện có liên quan, với \r\ncác bản ghi riêng biệt. Nếu dấu phân cách đó được viết ở chế độ văn bản, thì thời gian chạy Python thay thế \nbằng \r\n, do đó \r\r\nđược quan sát trong tệp.

Xem câu trả lời trước .


3
Điều này tốt cho ASCII nhưng sẽ giết mã hóa như UTF-8. Giải pháp của Jason dưới đây đã làm việc cho tôi.
Tom

66
Trong Python 3, tôi đã có thể sửa nó bằng cách sử dụng các tùy chọn sau cho đối tượng tệp : open(..., "w", newline="\n", encoding="utf-8"). newlinecũng có thể là một chuỗi trống, kết quả tương tự. "wb"không hoạt động trong Python 3, các chuỗi và giao diện bộ đệm không tương thích.
CodeManX

Cách xử lý thanh lịch trả lại xe ngựa thêm
ForeverLearner

2
Không hoạt động trong Python2, vì vậy nếu bạn cần tương thích với cả 2 và 3, hãy sử dụng câu trả lời được đưa ra bởi @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
Đây là một sự xấu hổ thực sự khi một API cơ bản, phổ biến và đơn giản như vậy không hoạt động như yêu cầu
SomethingS Something

248

Mặc dù @ john-machin đưa ra một câu trả lời hay, nhưng nó không phải lúc nào cũng là cách tiếp cận tốt nhất. Ví dụ: nó không hoạt động trên Python 3 trừ khi bạn mã hóa tất cả các đầu vào của mình cho trình ghi CSV. Ngoài ra, nó không giải quyết vấn đề nếu tập lệnh muốn sử dụng sys.stdout làm luồng.

Tôi đề nghị thay vì đặt thuộc tính 'lineterminator' khi tạo trình soạn thảo:

import csv
import sys

doc = csv.writer(sys.stdout, lineterminator='\n')
doc.writerow('abc')
doc.writerow(range(3))

Ví dụ đó sẽ hoạt động trên Python 2 và Python 3 và sẽ không tạo ra các ký tự dòng mới không mong muốn. Tuy nhiên, lưu ý rằng nó có thể tạo ra các dòng mới không mong muốn (bỏ qua ký tự LF trên các hệ điều hành Unix).

Tuy nhiên, trong hầu hết các trường hợp, tôi tin rằng hành vi đó là tốt hơn và tự nhiên hơn là coi tất cả CSV là định dạng nhị phân. Tôi cung cấp câu trả lời này như là một thay thế cho sự xem xét của bạn.


6
Đây là câu trả lời tốt nhất theo ý kiến ​​của tôi. Đối với nó đang có vấn đề trong Unix, làm thế nào về việc gọi sys.pl platform và xử lý nó một cách linh hoạt?
sovemp

4
Câu trả lời hay nhất theo ý kiến ​​của tôi cũng vậy, và lineterminator = '\ n' hoạt động rất đẹp.
eikonal

1
Bạn có thể đưa ra một ví dụ về vấn đề phát sinh nếu bạn không "mã hóa tất cả các đầu vào của mình cho người viết CSV" không?
Stephen

THƯỞNG: sử dụng phương tiện \rnày không còn được thoát! Có vẻ như đây là lỗi csvwriter, nhưng vì hiện tại, việc xuất ra CSV không tuân thủ có nghĩa là đây không phải là hướng đi.
Flow2k

Điều này đã giải quyết ^Mvấn đề cho tôi trong khi 2 đề xuất của câu trả lời được chấp nhận không hoạt động.
dùng985366

55

Trong Python 3 (Tôi chưa thử điều này trong Python 2), bạn cũng có thể chỉ cần làm

with open('output.csv','w',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(mystuff)
    ...

theo tài liệu .

Thêm về điều này trong chú thích của tài liệu :

Nếu newline = '' không được chỉ định, các dòng mới được nhúng bên trong các trường được trích dẫn sẽ không được hiểu chính xác và trên các nền tảng sử dụng \ r \ n linendings khi viết thêm \ r sẽ được thêm vào. Sẽ luôn an toàn khi chỉ định newline = '', vì mô-đun csv thực hiện xử lý dòng mới (phổ quát) của riêng nó.


2
@ Yibo-Yang, Bạn đã tiết kiệm cho tôi rất nhiều thời gian.
1man

4
TUYỆT QUÁ. Tôi khẳng định như vậy trong python 3.5
Jef

Tại sao đây không phải là hành vi mặc định?
Marc Stober

6

Bạn có thể giới thiệu tham số lineterminator = '\ n' trong lệnh nhà văn csv.

import csv
delimiter='\t'
with open('tmp.csv', '+w', encoding='utf-8') as stream:
    writer = csv.writer(stream, delimiter=delimiter, quoting=csv.QUOTE_NONE, quotechar='',  lineterminator='\n')
    writer.writerow(['A1' , 'B1', 'C1'])
    writer.writerow(['A2' , 'B2', 'C2'])
    writer.writerow(['A3' , 'B3', 'C3'])

1
Với Python 3.5.2, đây là thứ duy nhất hoạt động với tôi (tốt, tôi chỉ sử dụng lineterminator='\n'); mô-đun CSV dường như là nguồn gốc của \r\n. Không có tập hợp các đối số để opencó bất kỳ hiệu ứng.
Tommy

5

Tôi không chắc chắn chính xác tại sao nó lại xảy ra, nhưng việc thay đổi chế độ tệp của bạn từ "w" sang "wb" sẽ sửa nó. Xem câu trả lời của tôi về " cách xóa ^ M " để biết thêm chi tiết.


3

Bạn phải thêm thuộc tính newline = "\ n" để mở chức năng như thế này:

with open('file.csv','w',newline="\n") as out:
    csv_out = csv.writer(out, delimiter =';')

2

Lưu ý rằng nếu bạn sử dụng DictWriter, bạn sẽ có một dòng mới từ hàm mở và một dòng mới từ hàm wrow. Bạn có thể sử dụng newline = '' trong chức năng mở để xóa dòng mới bổ sung.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.