CSV in Python, das unter Windows einen zusätzlichen Wagenrücklauf hinzufügt


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()

Es generiert eine Datei test.csvmit einem Extra \rin jeder Zeile, wie folgt:

test.csv

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

anstelle der erwarteten:

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

Warum passiert das oder ist das tatsächlich das gewünschte Verhalten?

Hinweis:

  • Dieses Verhalten kann bei Python 2 oder 3 auftreten.

Antworten:


311

Python 3:

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

Python 2:

Öffnen Sie Ihre Dateien unter Windows immer im Binärmodus ( "rb"oder "wb"), bevor Sie sie an csv.readeroder übergeben csv.writer.

Obwohl es sich bei der Datei um eine Textdatei handelt, wird CSV von den beteiligten Bibliotheken als Binärformat mit \r\ngetrennten Datensätzen angesehen. Wenn dieses Trennzeichen im Textmodus geschrieben ist, ersetzt die Python-Laufzeit das \nmit \r\n, daher das \r\r\nin der Datei beobachtete.

Siehe diese vorherige Antwort .


3
Dies ist in Ordnung für ASCII, beendet jedoch die Codierung wie UTF-8. Jasons Lösung unten hat für mich funktioniert.
Tom

66
In Python 3 konnte ich das Problem mithilfe der folgenden Optionen für das Dateiobjekt beheben : open(..., "w", newline="\n", encoding="utf-8"). newlinekann auch eine leere Zeichenfolge sein, gleiches Ergebnis. "wb"funktioniert nicht in Python 3, Zeichenfolgen und die Pufferschnittstelle sind nicht kompatibel.
CodeManX

Elegante Art der Handhabung des zusätzlichen Wagenrücklaufs
ForeverLearner

2
Funktioniert nicht in Python2. Wenn Sie also mit 2 und 3 kompatibel sein müssen, verwenden Sie die Antwort von @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
Dies ist eine echte Schande, dass eine so grundlegende, gemeinsame und einfache API nicht wie erforderlich funktioniert
SomethingSomething

248

Während @ John-Machin eine gute Antwort gibt, ist es nicht immer der beste Ansatz. Beispielsweise funktioniert es unter Python 3 nur, wenn Sie alle Ihre Eingaben in den CSV-Writer codieren. Außerdem wird das Problem nicht behoben, wenn das Skript sys.stdout als Stream verwenden möchte.

Ich schlage vor, stattdessen das Attribut 'lineterminator' beim Erstellen des Writers festzulegen:

import csv
import sys

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

Dieses Beispiel funktioniert mit Python 2 und Python 3 und erzeugt keine unerwünschten Zeilenumbrüche. Beachten Sie jedoch, dass es zu unerwünschten Zeilenumbrüchen kommen kann (das LF-Zeichen unter Unix-Betriebssystemen wird weggelassen).

In den meisten Fällen glaube ich jedoch, dass Verhalten vorzuziehen und natürlicher ist, als alle CSVs als Binärformat zu behandeln. Ich gebe diese Antwort als Alternative für Ihre Überlegung.


6
Dies ist meiner Meinung nach die beste Antwort. Wie wäre es, wenn Sie sys.platform aufrufen und dynamisch damit umgehen, wenn es unter Unix problematisch ist?
Sovemp

4
Die beste Antwort meiner Meinung nach auch, und lineterminator = '\ n' funktioniert wunderbar.
Eikonal

1
Können Sie ein Beispiel für das Problem geben, das auftritt, wenn Sie nicht "alle Ihre Eingaben in den CSV-Writer codieren"?
Stephen

ACHTUNG: Mit diesem Mittel \rwird nicht mehr entkommen! Sieht so aus, als wäre dies ein Fehler csvwriter, aber so wie es aussieht , bedeutet die Ausgabe von nicht konformer CSV, dass dies nicht der richtige Weg ist.
flow2k

Dies löste das ^MProblem für mich, während die 2 Vorschläge der akzeptierten Antwort nicht funktionierten.
user985366

55

In Python 3 (ich habe dies in Python 2 nicht versucht) können Sie dies auch einfach tun

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

gemäß Dokumentation .

Mehr dazu in der Fußnote des Dokuments :

Wenn newline = '' nicht angegeben wird, werden in Anführungszeichen eingebettete Zeilenumbrüche nicht korrekt interpretiert, und auf Plattformen, die beim Schreiben \ r \ n Linendings verwenden, wird ein zusätzliches \ r hinzugefügt. Es sollte immer sicher sein, newline = '' anzugeben, da das CSV-Modul seine eigene (universelle) Newline-Behandlung durchführt.


2
@ Yibo-Yang, Du hast mir viel Zeit gespart.
1man

4
GROSSARTIG. Ich bestätigte diesen Weg in Python 3.5
jef

Warum ist dies nicht das Standardverhalten?
Marc Stober

6

Sie können den Parameter lineterminator = '\ n' in den Befehl csv writer einfügen .

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
Mit Python 3.5.2 war dies das einzige, was für mich funktioniert hat (nun, ich habe es nur verwendet lineterminator='\n'). Das CSV-Modul schien der Ursprung von zu sein \r\n. Keine Reihe von Argumenten, opendie irgendeine Wirkung hatten.
Tommy

5

Ich bin mir nicht sicher, warum es genau passiert, aber wenn Sie Ihren Dateimodus von "w" auf "wb" ändern, wird das Problem behoben. Weitere Informationen finden Sie in meiner Antwort auf " Entfernen von ^ M ".


3

Sie müssen das Attribut newline = "\ n" hinzufügen, um die Funktion wie folgt zu öffnen:

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

2

Beachten Sie, dass Sie bei Verwendung von DictWriter eine neue Zeile aus der Öffnungsfunktion und eine neue Zeile aus der Writerow-Funktion erhalten. Sie können newline = '' in der Öffnungsfunktion verwenden, um die zusätzliche Newline zu entfernen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.