CSV в Python с добавлением дополнительного возврата каретки в Windows
В Python 2.7, работающем на Windows XP pro:
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()
Он генерирует файл test.csv с дополнительным \r в каждой строке, например:
test.csv
hi,dude\r\r\nhi2,dude2\r\r\n
вместо ожидаемого:
hi,dude\r\nhi2,dude2\r\n
Почему это происходит, или это действительно желаемое поведение?
7 ответов
В Windows всегда открывайте файлы в двоичном режиме ("rb" или "wb"), прежде чем передавать их в csv.reader или csv.writer.
Хотя файл представляет собой текстовый файл, участвующие библиотеки рассматривают CSV как двоичный формат с разделением записей "\ r \ n". Если этот разделитель записан в текстовом режиме, среда выполнения Python заменяет "\ n" на "\ r \ n", следовательно, "\ r \ r \ n", который вы наблюдали в вашем файле.
Смотрите этот предыдущий ответ.
Этот ответ был опубликован в 2010 году и не решает проблему в Python3.
Одним из возможных исправлений в Python3, как описано в ответе @YiboYang, является открытие файла с newline
параметр установлен как пустая строка:
f = open(path_to_file, 'w', newline='')
writer = csv.writer(f)
...
...
Хотя @john-machin дает хороший ответ, это не всегда лучший подход. Например, он не работает на Python 3, если вы не закодируете все свои входные данные для средства записи CSV. Кроме того, это не решает проблему, если скрипт хочет использовать sys.stdout в качестве потока.
Вместо этого я предлагаю установить атрибут 'lineterminator' при создании писателя:
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 в двоичном формате. Я предоставляю этот ответ в качестве альтернативы для вашего рассмотрения.
В Python 3 (я не пробовал это в Python 2), вы также можете просто сделать
with open('output.csv','w',newline='') as f:
writer=csv.writer(f)
writer.writerow(mystuff)
...
согласно документации
Подробнее об этом в сноске документа:
Если не указывать символ новой строки ='', символы новой строки, встроенные в поля в кавычках, будут интерпретироваться неправильно, и на платформах, использующих строки \ r \ n при записи, будет добавлен дополнительный символ \ r. Всегда должно быть безопасно указывать newline ='', поскольку модуль csv выполняет свою собственную (универсальную) обработку новой строки.
Вы можете ввести параметр lineterminator='\n' в команде csv writer.
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'])
Я не уверен точно, почему это происходит, но изменение режима файла с "w" на "wb" исправляет это. Смотрите мой ответ на " как удалить ^ M" для более подробной информации.
Вы должны добавить атрибут newline="\n", чтобы открыть функцию следующим образом:
with open('file.csv','w',newline="\n") as out:
csv_out = csv.writer(out, delimiter =';')
Обратите внимание, что если вы используете DictWriter, у вас будет новая строка из функции open и новая строка из функции writerow. Вы можете использовать newline='' в функции open, чтобы удалить лишнюю новую строку.