Il file CSV scritto con Python ha righe vuote tra ogni riga


446
import csv

with open('thefile.csv', 'rb') as f:
  data = list(csv.reader(f))
  import collections
  counter = collections.defaultdict(int)

  for row in data:
        counter[row[10]] += 1


with open('/pythonwork/thefile_subset11.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in data:
        if counter[row[10]] >= 504:
           writer.writerow(row)

Questo codice legge thefile.csv, apporta modifiche e scrive i risultati in thefile_subset1.

Tuttavia, quando apro il CSV risultante in Microsoft Excel, dopo ogni record c'è una riga vuota in più!

C'è un modo per fare in modo che non metta una linea in bianco?


4
Conferma che ciò accade quando esegui quel codice su Windows
John Machin,


Vedere la risposta su questa discussione: stackoverflow.com/questions/3348460/...
Febin Mathew

Risposte:


889

In Python 2, apri outfilecon mode 'wb'invece di 'w'. Le csv.writerscritture\r\n nel file direttamente. Se non si apre il file in modalità binaria , verrà scritto \r\r\nperché in modalità testo di Windows tradurrà ciascuno \nin \r\n.

In Python 3 la sintassi richiesta è cambiata (vedi i collegamenti alla documentazione di seguito), quindi apri outfilecon il parametro aggiuntivo newline=''(stringa vuota).

Esempi:

# Python 2
with open('/pythonwork/thefile_subset11.csv', 'wb') as outfile:
    writer = csv.writer(outfile)

# Python 3
with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
    writer = csv.writer(outfile)

Link alla documentazione


1
Ad ogni modo, la risposta di @Mark Tolonen ha risolto molte domande relative alle righe extra aggiunte durante il salvataggio di un file di testo standard (non usato da CSV).
Dlewin,

1
Per compatibilità tra 2.6 / 2.7 e 3, è possibile utilizzare io.opencon l' newlinesargomento. Se stai ancora scrivendo in 2.x, sembra comunque una scelta migliore poiché è compatibile in avanti.
jpmc26,

@ jpmc26 Normalmente è un buon consiglio, ma il modulo CSV non funziona correttamente io.open. Esiste un unicodecsvmodulo di terze parti per Python 2.7 che funziona meglio.
Mark Tolonen,

Qualche idea sul perché il newline=''trucco non funzioni in python3 con StringIO o TemporaryFile?
fmoo,

@fmoo define "non funziona". Entrambi funzionano come mi aspetto. StringIObufferizza gli stessi punti di codice che verrebbero codificati in un file e TemporaryFilesupporta il newlineparametro, quindi può essere aperto come con open. Fai una domanda con un programma di esempio che non funziona.
Mark Tolonen il

65

L'apertura del file in modalità binaria "wb" non funzionerà in Python 3+. O meglio, dovresti convertire i tuoi dati in binari prima di scriverli. È solo una seccatura.

Invece, dovresti tenerlo in modalità testo, ma sovrascrivere la nuova riga come vuota. Così:

with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:

13

La semplice risposta è che i file CSV devono sempre essere aperti in modalità binaria, sia per l'input che per l'output, altrimenti su Windows ci sono problemi con la fine della linea. Specificamente sull'uscita del modulo csv scriverà \r\n(CSV fila terminatore standard) e poi (in modo testo) il runtime sostituirà il \ndal \r\n(terminatore di linea standard di Windows) dando un risultato di \r\r\n.

Giocherellare con il lineterminatorNON è la soluzione.


Cos'è questo "standard" CSV di cui parli?
Dan Breslau,

3
@Dan: ho usato "standard" come aggettivo, non come sostantivo, che significa "solito" o "luogo comune". Se vuoi un'approssimazione a uno standard (sostantivo), leggi tools.ietf.org/html/rfc4180
John Machin

1
Il punto è (come intendi) che non esiste uno standard. Quel RFE è informativo. Sebbene \ r \ n possa essere "standard" su Windows, sono sicuro che le applicazioni Unix in genere non la vedono in questo modo.
Dan Breslau,

2
@Dan: è corretto - non esiste uno standard. Gli script dovrebbero specificare il lineterminatore [avrebbe dovuto essere chiamato ROWterminator] che desiderano (se non il valore predefinito) e utilizzare comunque la modalità binaria nel caso in cui lo script venga eseguito su Windows, altrimenti il ​​"lineterminatore" potrebbe essere riempito.
John Machin,

8

Nota: sembra che questa non sia la soluzione preferita a causa del modo in cui la linea aggiuntiva è stata aggiunta su un sistema Windows. Come indicato nel documento di Python :

Se csvfile è un oggetto file, deve essere aperto con il flag 'b' su piattaforme dove ciò fa la differenza.

Windows è una di queste piattaforme in cui ciò fa la differenza. Mentre la modifica del terminatore di linea come descritto di seguito potrebbe aver risolto il problema, il problema potrebbe essere evitato del tutto aprendo il file in modalità binaria. Si potrebbe dire che questa soluzione è più "elegante". "Giocherellare" con il terminatore di linea avrebbe probabilmente comportato un codice non negoziabile tra i sistemi in questo caso, in cui l'apertura di un file in modalità binaria su un sistema unix non produce alcun effetto. vale a dire. risulta in un codice compatibile tra sistemi.

Da Python Docs :

Su Windows, "b" aggiunto alla modalità apre il file in modalità binaria, quindi esistono anche modalità come "rb", "wb" e "r + b". Python su Windows fa una distinzione tra file di testo e file binari; i caratteri di fine riga nei file di testo vengono automaticamente modificati leggermente quando i dati vengono letti o scritti. Questa modifica dietro le quinte dei dati dei file va bene per i file di testo ASCII, ma corromperà i dati binari come quelli nei file JPEG o EXE. Prestare molta attenzione all'utilizzo della modalità binaria durante la lettura e la scrittura di tali file. Su Unix, non fa male aggiungere una "b" alla modalità, quindi puoi usarla in modo indipendente dalla piattaforma per tutti i file binari.

Originale :

Come parte dei parametri opzionali per csv.writer se stai ottenendo ulteriori righe vuote potresti dover cambiare il lineterminatore (informazioni qui ). Esempio di seguito adattato dalla pagina python csv docs. Cambia da '\ n' a qualunque cosa dovrebbe essere. Dato che questo è solo un colpo al buio per il problema, questo può o non può funzionare, ma è la mia ipotesi migliore.

>>> import csv
>>> spamWriter = csv.writer(open('eggs.csv', 'w'), lineterminator='\n')
>>> spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
>>> spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

Stavo per postare su questo - lineterminator = '\ n' ha funzionato per me in un semplice test.
Dan Breslau,

posso fare questo> ?? con open ('/ pythonwork / thefile_subset11.csv', 'w'), lineterminator = '\ n' come outfile:
l --''''''---------------- '' '' ' '' '' '' '27

1
@I__: dovresti davvero iniziare a leggere i documenti di Python. Derek ti ha fornito il link: docs.python.org/library/csv.html
Dan Breslau,

5

Sto scrivendo questa risposta scritta su Python 3, poiché inizialmente ho avuto lo stesso problema.

Avrei dovuto ottenere dati da Arduino usando PySeriale scriverli in un file .csv. Ogni lettura nel mio caso si è conclusa con'\r\n' , quindi newline separava sempre ogni riga.

Nel mio caso, l' newline=''opzione non ha funzionato. Perché ha mostrato alcuni errori come:

with open('op.csv', 'a',newline=' ') as csv_file:

ValueError: illegal newline value: ''

Quindi sembrava che qui non accettassero l'omissione di newline.

Vedendo solo una delle risposte qui, ho citato il terminatore di riga nell'oggetto writer, come

writer = csv.writer(csv_file, delimiter=' ',lineterminator='\r')

e questo ha funzionato per me nel saltare le nuove righe extra.


2
Questo non è corretto with open('my_file.csv', 'a',newline='') as csvfile: funziona assolutamente bene. Il problema con la tua risposta è che qui stai scrivendo ' 'invece di''
Nasrin,

2
with open(destPath+'\\'+csvXML, 'a+') as csvFile:
    writer = csv.writer(csvFile, delimiter=';', lineterminator='\r')
    writer.writerows(xmlList)

Il "lineterminator = '\ r'" consente di passare alla riga successiva, senza riga vuota tra due.


1

Prendendo in prestito da questa risposta , sembra che la soluzione più pulita sia usare io.TextIOWrapper. Sono riuscito a risolvere questo problema per me stesso come segue:

from io import TextIOWrapper

...

with open(filename, 'wb') as csvfile, TextIOWrapper(csvfile, encoding='utf-8', newline='') as wrapper:
    csvwriter = csv.writer(wrapper)
    for data_row in data:
        csvwriter.writerow(data_row)

La risposta di cui sopra non è compatibile con Python 2. Per avere compatibilità, suppongo che si debba semplicemente avvolgere tutta la logica di scrittura in un ifblocco:

if sys.version_info < (3,):
    # Python 2 way of handling CSVs
else:
    # The above logic

0

Utilizzare il metodo definito di seguito per scrivere i dati nel file CSV.

open('outputFile.csv', 'a',newline='')

Basta aggiungere un newline=''parametro aggiuntivo all'interno del openmetodo:

def writePhoneSpecsToCSV():
    rowData=["field1", "field2"]
    with open('outputFile.csv', 'a',newline='') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(rowData)

Questo scriverà righe CSV senza creare righe aggiuntive!


-1

Quando si utilizza Python 3, è possibile evitare le righe vuote utilizzando il modulo codecs . Come indicato nella documentazione, i file vengono aperti in modalità binaria, quindi non è necessario modificare la nuova riga kwarg. Recentemente stavo riscontrando lo stesso problema e questo ha funzionato per me:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)
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.