CSV в Python с добавлением дополнительного возврата каретки в Windows

232
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

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

Примечание:

  • Такое поведение может происходить с Python 2 или 3.
apalopohapa
источник
Возможный дубликат Python 2 CSV
Джон Y

Ответы:

312

Python 3:

  • Как описано YiboYang , установитеnewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Как отмечено в комментариях CoDEmanX , установитеnewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

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

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

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

Джон Мачин
источник
3
Это хорошо для ASCII, но убьет кодирование как UTF-8. Приведенное ниже решение Джейсона сработало для меня.
Том
66
В Python 3, я был в состоянии исправить это с помощью следующих параметров для объекта файла: open(..., "w", newline="\n", encoding="utf-8"). newlineтакже может быть пустой строкой, тот же результат. "wb"не работает в Python 3, строки и интерфейс буфера несовместимы.
CodeManX
Элегантный способ справиться с дополнительным возвратом каретки
ForeverLearner
2
Не работает в Python2, поэтому, если вам нужно быть совместимым как с 2, так и с 3, используйте ответ, заданный @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74
4
Это настоящий позор, что такой базовый, общий и простой API не работает должным образом
SomethingSomething
249

Хотя @ 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 как двоичного формата. Я предоставляю этот ответ в качестве альтернативы для вашего рассмотрения.

Джейсон Р. Кумбс
источник
6
Это лучший ответ на мой взгляд. Что касается проблем в Unix, как насчет вызова sys.platform и динамического обращения с ним?
Совэмп
4
На мой взгляд, лучший ответ, и lineterminator = '\ n' работает прекрасно.
Eikonal
1
Можете ли вы привести пример проблемы, которая возникает, если вы не «закодируете все свои входные данные в CSV-писатель»?
Стивен
ВНИМАНИЕ: с помощью этого средства \rбольше не избежать! Похоже, что это ошибка csvwriter, но на самом деле вывод несовместимого CSV означает, что это не тот путь.
flow2k
Это решило ^Mпроблему для меня, в то время как принятый ответ 2 предложения не работал.
user985366
55

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

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

в соответствии с документацией .

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

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

Ибо Ян
источник
2
@ Yibo-Yang, ты сэкономил мне много времени.
1
4
ЗДОРОВО. Я подтвердил это в Python 3.5
JEF
Почему это не было бы поведением по умолчанию?
Марк Стобер
7

Вы можете ввести параметр 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'])
Весам На
источник
1
С Python 3.5.2 это было единственное, что работало для меня (ну, я использовал только lineterminator='\n'); модуль CSV, казалось, был источником \r\n. Никакой набор аргументов не openимел никакого эффекта.
Томми
5

Я не уверен точно, почему это происходит, но изменение режима файла с "w" на "wb" исправляет это. Смотрите мой ответ на " как удалить ^ M " для более подробной информации.

Нед Бэтчелдер
источник
3

Вы должны добавить атрибут newline = "\ n", чтобы открыть функцию следующим образом:

with open('file.csv','w',newline="\n") as out:
    csv_out = csv.writer(out, delimiter =';')
Грегор Ажбе
источник
2

Обратите внимание, что если вы используете DictWriter, у вас будет новая строка из функции open и новая строка из функции writerow. Вы можете использовать newline = '' внутри функции open, чтобы удалить лишнюю новую строку.

Эрик Стоун
источник