Вопрос-Ответ

CSV in Python adding an extra carriage return, on Windows

CSV в Python, добавляющий дополнительный возврат каретки в Windows
import csv

with open('test.csv', 'w') as outfile:
writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['hi', 'dude'])
writer.writerow(['hi2', 'dude2'])

Приведенный выше код генерирует файл, test.csv с дополнительным \r в каждой строке, вот так:

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

вместо ожидаемого

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

Почему это происходит, или это действительно желаемое поведение?

Переведено автоматически
Ответ 1

Python 3:

Официальная csv документация рекомендует openредактировать файл с помощью newline='' на всех платформах, чтобы отключить универсальный перевод новых строк:

with open('output.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
...

Программа записи CSV завершает каждую строку lineterminator диалектом, который является '\r\n' для диалекта по умолчанию excel на всех платформах, потому что это то, что рекомендует RFC 4180.


Python 2:

В Windows всегда открывайте свои файлы в двоичном режиме ("rb" или "wb"), прежде чем передавать их в csv.reader или csv.writer.

Хотя файл является текстовым, задействованные библиотеки рассматривают CSV как двоичный формат с \r\n разделяющими записями. Если этот разделитель записан в текстовом режиме, среда выполнения Python заменяет его \n на \r\n, следовательно, \r\r\n наблюдается в файле.

Смотрите этот предыдущий ответ.

Ответ 2

Хотя @john-machin дает хороший ответ, это не всегда лучший подход. Например, это не работает на Python 3, если вы не закодируете все свои входные данные в программу записи CSV. Также это не решает проблему, если скрипт хочет использовать sys.stdout в качестве потока.

Я предлагаю вместо этого установить атрибут 'lineterminator' при создании writer:

import csv
import sys

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

Этот пример будет работать на Python 2 и Python 3 и не приведет к появлению нежелательных символов новой строки. Однако обратите внимание, что он может привести к появлению нежелательных символов новой строки (без символа LF в операционных системах Unix).

Однако в большинстве случаев я считаю, что такое поведение предпочтительнее и естественнее, чем обработка всего CSV в двоичном формате. Я предоставляю этот ответ в качестве альтернативы для вашего рассмотрения.

Ответ 3

В Python 3 (я не пробовал этого в Python 2) вы также можете просто сделать

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

согласно документации.

Подробнее об этом в сноске к документу:


Если значение newline=" не указано, новые строки, встроенные в поля, заключенные в кавычки, не будут интерпретироваться правильно, и на платформах, которые используют \r\n подстановки при записи, будет добавлен дополнительный \r . Всегда должно быть безопасно указывать newline=", поскольку модуль csv выполняет свою собственную (универсальную) обработку перевода строки.


Ответ 4

Вы можете ввести параметр lineterminator='\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'])
python windows csv