CSV in Python aggiungendo un ritorno a capo extra, su 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()

Genera un file, test.csvcon un extra \rin ogni riga, in questo modo:

test.csv

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

invece del previsto:

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

Perché sta succedendo o è in realtà il comportamento desiderato?

Nota:

  • Questo comportamento può verificarsi con Python 2 o 3.

Risposte:


311

Python 3:

  • Come descritto da YiboYang , impostarenewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Come notato nei commenti di CoDEmanX , impostarenewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

Su Windows, apri sempre i tuoi file in modalità binaria ( "rb"o "wb"), prima di passarli a csv.readero csv.writer.

Sebbene il file sia un file di testo, CSV è considerato un formato binario dalle librerie coinvolte, con \r\nrecord di separazione. Se quel separatore è scritto in modalità testo, il runtime di Python sostituisce \ncon \r\n, quindi l' \r\r\nosservato nel file.

Vedi questa risposta precedente .


3
Questo va bene per ASCII ma ucciderà la codifica come UTF-8. La soluzione di Jason qui sotto ha funzionato per me.
Tom

66
In Python 3, sono stato in grado di risolvere il problema utilizzando le seguenti opzioni per l'oggetto file: open(..., "w", newline="\n", encoding="utf-8"). newlinepuò anche essere una stringa vuota, stesso risultato. "wb"non funziona in Python 3, le stringhe e l'interfaccia buffer sono incompatibili.
CodeManX,

Modo elegante di gestire il ritorno del trasporto extra
ForeverLearner

2
Non funziona in Python2, quindi se devi essere compatibile con 2 e 3, usa la risposta data da @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
È un vero peccato che un'API così semplice, comune e semplice non funzioni come richiesto
SomethingSomething

248

Mentre @ john-machin dà una buona risposta, non è sempre l'approccio migliore. Ad esempio, non funziona su Python 3 a meno che non codifichi tutti i tuoi input nel writer CSV. Inoltre, non risolve il problema se lo script desidera utilizzare sys.stdout come flusso.

Suggerisco invece di impostare l'attributo 'lineterminator' durante la creazione del writer:

import csv
import sys

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

Quell'esempio funzionerà su Python 2 e Python 3 e non produrrà i caratteri di nuova riga indesiderati. Si noti, tuttavia, che potrebbe produrre newline indesiderate (omettendo il carattere LF sui sistemi operativi Unix).

Nella maggior parte dei casi, tuttavia, ritengo che il comportamento sia preferibile e più naturale del trattamento di tutti i CSV come un formato binario. Fornisco questa risposta come alternativa alla tua considerazione.


6
Questa è la migliore risposta secondo me. Quanto problematico in Unix, che ne dici di chiamare sys.platform e gestirlo in modo dinamico?
Sovemp

4
Anche la migliore risposta secondo me, e lineterminator = '\ n' funziona magnificamente.
eikonal il

1
Puoi fare un esempio del problema che si presenta se non "codifichi tutti i tuoi input per il writer CSV"?
Stephen,

ATTENZIONE: l'utilizzo di questo mezzo \rnon è più sfuggito! Sembra che questo sia un bug csvwriter, ma così com'è, l'output di CSV non conforme significa che questa non è la strada da percorrere.
flow2k

Ciò ha risolto il ^Mproblema per me mentre i 2 suggerimenti della risposta accettata non funzionavano.
user985366

55

In Python 3 (non l'ho provato in Python 2), puoi anche semplicemente farlo

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

come da documentazione .

Maggiori informazioni su questo nella nota a piè di pagina del documento :

Se newline = '' non viene specificato, i newline incorporati nei campi tra virgolette non verranno interpretati correttamente e sulle piattaforme che usano \ r \ n linendings per scrivere verranno aggiunti altri \ r. Dovrebbe essere sempre sicuro specificare newline = '', poiché il modulo csv fa la sua gestione (universale) di newline.


2
@ Yibo-Yang, mi hai risparmiato un sacco di tempo.
uomo,

4
GRANDE. Ho confermato in questo modo in Python 3.5
jef

Perché questo non dovrebbe essere il comportamento predefinito?
Marc Stober,

6

È possibile introdurre il parametro lineterminator = '\ n' nel comando 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
Con Python 3.5.2, questa è stata l'unica cosa che ha funzionato per me (beh, l'ho usato solo lineterminator='\n'); il modulo CSV sembrava essere l'origine di \r\n. Nessuna serie di argomenti ha openavuto alcun effetto.
Tommy

5

Non sono sicuro del perché accada, ma la modifica della modalità del file da "w" a "wb" lo risolve. Vedi la mia risposta a " come rimuovere ^ M " per maggiori dettagli.


3

Devi aggiungere l'attributo newline = "\ n" per aprire la funzione in questo modo:

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

2

Nota che se usi DictWriter, avrai una nuova riga dalla funzione open e una nuova riga dalla funzione writerow. È possibile utilizzare newline = '' all'interno della funzione aperta per rimuovere la nuova riga aggiuntiva.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.