CSV w Pythonie dodaje dodatkowy znak powrotu karetki w systemie 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()

Generuje plik, test.csvz dodatkowym \rw każdym wierszu, tak:

test.csv

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

zamiast oczekiwanego:

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

Dlaczego tak się dzieje, czy jest to pożądane zachowanie?

Uwaga:

  • Takie zachowanie może wystąpić w Pythonie 2 lub 3.

Prawdopodobnie duplikat programu piszącego CSV
John Y,

Odpowiedzi:


311

Python 3:

  • Zgodnie z opisem YiboYanga , ustawnewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Jak zauważono w komentarzach CoDEmanX , ustawnewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

W systemie Windows zawsze otwieraj pliki w trybie binarnym ( "rb"lub "wb") przed przekazaniem ich do csv.readerlub csv.writer.

Mimo że plik jest plikiem tekstowym, zaangażowane biblioteki uznają format binarny za \r\noddzielny. Jeśli to separator jest napisane w trybie tekstowym, środowisko wykonawcze Python zastępuje \nsię \r\n, stąd \r\r\nobserwowane w pliku.

Zobacz poprzednią odpowiedź .


3
Jest to w porządku dla ASCII, ale zabija kodowanie jak UTF-8. Poniższe rozwiązanie Jasona zadziałało dla mnie.
Tom

66
W Pythonie 3, udało mi się go naprawić za pomocą następujących opcji dla obiektu pliku: open(..., "w", newline="\n", encoding="utf-8"). newlinemoże być również pustym ciągiem, tym samym wynikiem. "wb"nie działa w Pythonie 3, łańcuchy i interfejs bufora są niekompatybilne.
CodeManX

Elegancki sposób obsługi dodatkowego zwrotu karetki
ForeverLearner

2
Nie działa w Python2, więc jeśli chcesz być zgodny zarówno z 2, jak i 3, skorzystaj z odpowiedzi udzielonej przez @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
To wielka szkoda, że ​​taki podstawowy, powszechny i ​​prosty interfejs API nie działa zgodnie z wymaganiami
SomethingSomething

248

Chociaż @ john-machin daje dobrą odpowiedź, nie zawsze jest to najlepsze podejście. Na przykład nie działa w Pythonie 3, chyba że kodujesz wszystkie dane wejściowe do programu piszącego CSV. Ponadto nie rozwiązuje problemu, jeśli skrypt chce użyć sys.stdout jako strumienia.

Zamiast tego sugeruję ustawienie atrybutu „lineterminator” podczas tworzenia programu piszącego:

import csv
import sys

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

Ten przykład będzie działał na Python 2 i Python 3 i nie będzie generował niepożądanych znaków nowej linii. Należy jednak pamiętać, że może powodować niepożądane znaki nowej linii (pomijając znak LF w systemach operacyjnych Unix).

Jednak w większości przypadków uważam, że zachowanie jest lepsze i bardziej naturalne niż traktowanie całego pliku CSV jako formatu binarnego. Podaję tę odpowiedź jako alternatywę do rozważenia.


6
To jest najlepsza odpowiedź moim zdaniem. Jeśli chodzi o problem w Uniksie, co powiesz na wywołanie sys.platform i radzenie sobie z tym dynamicznie?
sovemp,

4
Moim zdaniem najlepsza odpowiedź, a lineterminator = '\ n' działa pięknie.
eikonal

1
Czy możesz podać przykład problemu, który powstaje, jeśli nie „zakodujesz wszystkich danych wejściowych do programu piszącego CSV”?
Stephen

UWAGA: korzystanie z tych środków \rnie jest już możliwe! Wygląda na to, że jest to błąd csvwriter, ale w tej chwili wyświetlanie niezgodnego CSV oznacza, że nie jest to właściwa droga.
flow2k

To rozwiązało ^Mproblem, podczas gdy 2 propozycje zaakceptowanej odpowiedzi nie zadziałały.
user985366

55

W Python 3 (nie próbowałem tego w Python 2), możesz po prostu to zrobić

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

zgodnie z dokumentacją .

Więcej na ten temat w przypisie doktora :

Jeśli nie podano newline = '', nowe wiersze osadzone w polach cytowanych nie będą poprawnie interpretowane, a na platformach, które używają \ r \ n podszewek przy pisaniu, zostaną dodane dodatkowe \ r. Zawsze powinno być bezpiecznie określić newline = '', ponieważ moduł csv ma ​​własną (uniwersalną) obsługę nowej linii.


2
@ Yibo-Yang, zaoszczędziłeś mi dużo czasu.
1man

4
ŚWIETNY. Potwierdziłem to w Pythonie 3.5
jef

Dlaczego nie byłoby to zachowanie domyślne?
Marc Stober

6

Możesz wprowadzić parametr lineterminator = '\ n' w poleceniu piszącym 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
W przypadku Python 3.5.2 była to jedyna rzecz, która działała dla mnie (cóż, użyłem właśnie lineterminator='\n'); moduł CSV wydawał się być początkiem \r\n. Brak zestawu argumentów, które openmiałyby jakikolwiek skutek.
Tommy

5

Nie jestem pewien, dlaczego tak się dzieje, ale zmiana trybu pliku z „w” na „wb” naprawia to. Zobacz moją odpowiedź na „ jak usunąć ^ M ”, aby uzyskać więcej informacji.


3

Musisz dodać atrybut newline = "\ n", aby otworzyć funkcję w następujący sposób:

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

2

Zauważ, że jeśli użyjesz DictWriter, będziesz mieć nowy wiersz z funkcji open i nowy wiersz z funkcji writerow. Możesz użyć nowej linii = '' w ramach funkcji otwartej, aby usunąć dodatkową nową linię.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.