CSV в Python додає додатковий повернення каретки для 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()

Він генерує файл, test.csvз додатковим \rу кожному рядку, наприклад:

test.csv

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

замість очікуваного:

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

Чому це відбувається, чи це насправді бажана поведінка?

Примітка:

  • Така поведінка може відбуватися з Python 2 або 3.

Відповіді:


311

Пітон 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)
    ...

Пітон 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

248

Хоча @ 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 та динамічної роботи з ним?
sovemp

4
Найкраща відповідь і на мій погляд, і lineterminator = '\ n' працює прекрасно.
eikonal

1
Чи можете ви навести приклад проблеми, яка виникає, якщо ви не "кодуєте всі свої вкладення для запису CSV"?
Стівен

ПЕРЕБАЖУЙТЕ: використання цього засобу \rвже не уникає! Схоже, це помилка csvwriter, але, як існує, вихід невідповідних CSV означає, що це не шлях.
flow2k

Це вирішило ^Mпроблему для мене, поки 2 пропозиції прийнятої відповіді не спрацювали.
користувач985366

55

У 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 виконує власну (універсальну) обробку нового рядка.


2
@ Yibo-Yang, ти врятував мені багато часу.
1man,

4
ВЕЛИКИЙ. Я підтвердив це в python 3.5
jef

Чому б це не було поведінкою за замовчуванням?
Марк Стобер

6

Ви можете ввести параметр lineterminator = '\ n' в команду csv write .

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, у вас буде новий рядок із відкритої функції та новий рядок від функції запису. Ви можете використовувати newline = '' у межах відкритої функції, щоб видалити зайвий новий рядок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.