2015-04-24 16 views
11

EDIT: L'ho inserito nel titolo, ma ho appena realizzato che non l'ho menzionato nel corpo. Questo sembra essere specifico per Windows.Scrittura di un file .CSV in Python che funziona sia per Python 2.7+ che per Python 3.3+ in Windows

Ho difficoltà a scrivere l'output utilizzando il modulo Python csv in uno script che funziona con Python 2.7 e 3.3.

Prima prova che funziona come previsto in Python 2.7:

with open('test.csv', 'wb') as csv_file: 
    writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
    writer.writeheader() 
    for item in items: 
     writer.writerow(item) 

Tuttavia, quando quella stessa cosa viene eseguito in Python 3.3 si finisce con:

TypeError: 'str' does not support the buffer interface 

Così posso cambiare 'wb'-'wt' e funziona, ma ora ho una riga bianca in più su ogni altra riga nel file.

Per rimediare, posso cambiare:

with open('test.csv', 'wt') as csv_file: 

a:

with open('test.csv', 'wt', newline='') as csv_file: 

Ma ora, si rompe Python 2.7:

TypeError: 'newline' is an invalid keyword argument for this function 

So che potrei proprio fare qualcosa di simile :

try: 
    with open('test.csv', 'wt', newline='') as csv_file: 
     writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
     writer.writeheader() 
     for item in items: 
      writer.writerow(item) 
except TypeError: 
    with open('test.csv', 'wb') as csv_file: 
     writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
     writer.writeheader() 
     for item in items: 
      writer.writerow(item) 

Tuttavia, questo ha qualche duplicazione grave.

Qualcuno ha un modo più pulito per farlo?

EDIT: I dati di test è semplice e non ha ritorni a capo o qualsiasi cosa:

items = [{'header1': 'value', 'header2': 'value2'}, 
     {'header1': 'blah1', 'header2': 'blah2'}] 
+0

Non puoi semplicemente usare "w" anziché "wb" o "wt"? – nathancahill

+0

Le stringhe nella lista 'item' contengono stringhe 'unicode' quando si esegue lo script in Python 2? I valori sono sempre ASCII o potrebbero includere caratteri extra che devono essere codificati? Anche se sei in grado di eseguire lo stesso codice in entrambe le versioni di Python, potresti non ottenere gli stessi risultati! – Blckknght

+0

@Blckknght - Ho aggiunto i dati del test alla fine della domanda. È solo un testo ASCII. – Tamerz

risposta

6

Ho provato un paio di modi. Per quanto posso vedere, semplice utilizzando 'w' potrebbe essere una soluzione:

with open('test.csv', 'w') as csv_file: 
    writer = csv.DictWriter(csv_file, fieldnames=['header1', 'header2'], lineterminator='\n') 
    # write something 
+1

Se lo faccio, ottengo comunque linee vuote ogni altra riga. Hai provato questo in Windows o su qualcos'altro? – Tamerz

+0

@Tamerz Ottieni nuove linee extra perché hai nuove linee extra nei tuoi dati ... '.strip()' potrebbe essere quello che ti serve. – gboffi

+0

@Tamerz Ho provato con alcuni dati falsi e si è rivelato buono. Quindi penso che ci sia qualcosa di sbagliato anche nei tuoi dati. – skyline75489

7

Ecco un modo generico semplice:

import sys 

if sys.version_info[0] == 2: # Not named on 2.6 
    access = 'wb' 
    kwargs = {} 
else: 
    access = 'wt' 
    kwargs = {'newline':''} 

with open('test.csv', access, **kwargs) as csv_file: 
    writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
    writer.writeheader() 
    for item in items: 
     writer.writerow(item) 

Il principio non è quello di cercare di combattere le differenze tra Python 2 e 3 ma per avere un codice condizionale. Puoi solo andare così lontano scrivendo il codice senza questo tipo di test, prima o poi dovrai testare la versione di Python.

+0

Ho pensato che ottenere "** kwargs" potrebbe essere una buona soluzione. Non è ancora bello ma è significativamente migliore di tutte le duplicazioni che ho avuto. Questo funzionerà perfettamente nel mio scenario. Grazie. – Tamerz

+0

Sono andato con la risposta che @ skyline75489 ha dato, ma mi piace ancora per l'uso futuro. Ci sono volte in cui ho dovuto fare esattamente questo, ma non conoscevo il modo migliore. – Tamerz

+0

@Tamerz: dai un'occhiata [la mia risposta] (http://stackoverflow.com/a/41913382/355230) a una domanda simile. Funziona in entrambe le versioni di Python e gestisce l'apertura di file sia per la lettura che per la scrittura (inoltre. Come "open()", il valore predefinito è la modalità di lettura se non ne è stata specificata esplicitamente una). Inoltre non richiede l'uso di variabili globali. – martineau