2010-11-12 18 views
77

Sto lavorando con alcuni file CSV, con il seguente codice:Python CSV errore: riga contiene byte NULL

reader = csv.reader(open(filepath, "rU")) 
try: 
    for row in reader: 
     print 'Row read successfully!', row 
except csv.Error, e: 
    sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e)) 

e un file sta gettando questo errore:

file my.csv, line 1: line contains NULL byte 

cosa posso fare? Google sembra suggerire che potrebbe trattarsi di un file Excel che è stato salvato come .csv in modo errato. C'è un modo per aggirare questo problema in Python?

AGGIORNAMENTO == ==

seguito @ commento di JohnMachin di seguito, ho provato ad aggiungere queste righe al mio script:

print repr(open(filepath, 'rb').read(200)) # dump 1st 200 bytes of file 
data = open(filepath, 'rb').read() 
print data.find('\x00') 
print data.count('\x00') 

e questo è l'output che ho ottenuto:

'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00\ .... <snip> 
8 
13834 

Quindi il file contiene infatti NUL byte.

+0

Cosa significa "od -c" che assomiglia alla prima riga? –

+0

quale query dovrei eseguire, qualcosa come cat my.csv | od -c | Di Più ? con quello ottengo: 0000000 D e p a r t m e n t F a m i l – AP257

+0

Come viene generato il CSV? Da Excel, potresti provare un dialetto. Altrimenti guarda: http://stackoverflow.com/questions/2753022/python-finding-unicode-asci-problems –

risposta

1

Perché stai facendo questo?

reader = csv.reader(open(filepath, "rU")) 

La documentazione è abbastanza chiaro che si deve fare questo:

with open(filepath, "rb") as src: 
    reader= csv.reader(src) 

La modalità deve essere "rb" per leggere.

http://docs.python.org/library/csv.html#csv.reader

If csvfile is a file object, it must be opened with the ‘b’ flag on platforms where that makes a difference.

+2

Grazie, ma non aiuta ... – AP257

+0

@ AP257: "Non aiuta"? Significa che cosa? Qualche messaggio di errore specifico? –

+1

@ S.Lott: significa che ottiene la stessa risposta di prima. La realtà è che ha a che fare con un file camaleonte o mutaforma ... quando lo scarica con 'od' o lo guarda in un editor di testo, sembra un file CSV perfettamente normale. Tuttavia quando esegue il dump dei primi pochi byte con python repr(), si comporta come un file Excel .XLS (che è stato rinominato con un'estensione CSV). –

90

Come @ S. Lott dice, si dovrebbe aprire i file in modalità 'rb', non in modalità 'ru'. Tuttavia, questo NON può causare il tuo problema attuale. Per quanto ne so, l'uso della modalità 'rU' potrebbe rovinarti se ci sono dati \r incorporati nei dati, ma non causare altri drammi. Nota inoltre che hai diversi file (tutti aperti con 'rU' ??) ma solo uno causa un problema.

Se il modulo csv dice che nel file è presente un byte "NULL" (messaggio silly, dovrebbe essere "NUL"), è necessario controllare cosa è nel file. Ti suggerirei di farlo anche se l'uso di 'rb' fa andare via il problema.

repr() è (o vuole essere) il tuo amico di debug. Mostrerà inequivocabilmente ciò che hai, in una piattaforma indipendente (che è utile per gli helper che non sanno cosa sia o non sia od). Fare questo:

print repr(open('my.csv', 'rb').read(200)) # dump 1st 200 bytes of file 

e con attenzione copia/incolla (non digitare nuovamente) il risultato in una modifica della tua domanda (non in un commento).

Si noti inoltre che se il file è davvero rischioso, ad es. no \ r \ n entro ragionevole distanza dall'inizio del file, il numero di riga riportato da reader.line_num saranno (inutilmente) 1. Trovare dove il primo \x00 è (se presente) facendo

data = open('my.csv', 'rb').read() 
print data.find('\x00') 

e fare sicuro di aver scaricato almeno tanti byte con repr o od.

Che cosa dice data.count('\x00')?Se ce ne sono molti, potresti voler fare qualcosa come

for i, c in enumerate(data): 
    if c == '\x00': 
     print i, repr(data[i-30:i]) + ' *NUL* ' + repr(data[i+1:i+31]) 

in modo da poter vedere i byte NUL nel contesto.

Se è possibile vedere \x00 in uscita (o \0 nel vostro od -c uscita), quindi è sicuramente NUL byte (s) nel file, ed è necessario fare qualcosa di simile:

fi = open('my.csv', 'rb') 
data = fi.read() 
fi.close() 
fo = open('mynew.csv', 'wb') 
fo.write(data.replace('\x00', '')) 
fo.close() 

A proposito, hai guardato il file (comprese le ultime righe) con un editor di testo? In realtà sembra un file CSV ragionevole come l'altro (nessun file di eccezione "NULL byte")?

+0

Grazie mille per questo aiuto molto dettagliato. Ci sono molti caratteri \ x00 nel file (vedi modifica alla domanda) - è strano, perché in un editor di testo sembra un file CSV perfettamente ragionevole. – AP257

+1

@ AP257: ''\ xd0 \ xcf \ x11 \ xe0 \ xa1 \ xb1 \ x1a \ xe1' è la" firma "che denota un file di documento composto OLE2 - ad es. un ** file .XLS di Excel 97-2003 **. Trovo che "in un editor di testo sembra un file CSV perfettamente ragionevole" per essere ** assolutamente incredibile **. Devi aver guardato un file diverso, un file CSV valido, in un'altra cartella o su un'altra macchina o in un altro momento. Nota che il tuo output 'od' non proviene da un file XLS. –

+7

@ AP257: Qualche ragione particolare per cui non hai accettato questa risposta? –

2

appparently si tratta di un file XLS e non un file CSV come http://www.garykessler.net/library/file_sigs.html confermano

+0

Non necessariamente, ma sì, questo potrebbe essere una causa. Ho ricevuto questo errore quando ho provato l'analisi di un file CSV salvato da Excel da un file XLSX. – Cerin

+0

Con questo numero magico è la causa che XLSX ha un numero magico diverso –

12

mi sono imbattuto in questo problema pure. Utilizzando il modulo Python csv, stavo cercando di leggere un file XLS creato in MS Excel e in esecuzione nell'errore NULL byte che si stava ottenendo. Mi sono guardato intorno e ho trovato il modulo Python xlrd per leggere e formattare i dati dai file di foglio di lavoro di MS Excel. Con il modulo xlrd, non solo sono in grado di leggere correttamente il file, ma posso anche accedere a molte parti diverse del file in un modo che non potevo prima.

Ho pensato che potrebbe aiutarti.

+6

Grazie per aver segnalato quel modulo. È interessante notare che sono andato a scaricarlo e ho notato che l'autore era nientemeno che @John_Machin, che è anche il primo commento a questa domanda. – Evan

1

Ho ricevuto lo stesso errore. Salvato il file in UTF-8 e ha funzionato.

+1

Potrebbe essere stato visualizzato lo stesso messaggio di errore, ma la causa sarebbe stata diversa: probabilmente lo si è salvato inizialmente come UTF-16 (quale Blocco note chiama "Unicode"). –

10

La conversione della codifica del file sorgente da UTF-16 a UTF-8 risolve il mio problema.

How to convert a file to utf-8 in Python?

import codecs 
BLOCKSIZE = 1048576 # or some other, desired size in bytes 
with codecs.open(sourceFileName, "r", "utf-16") as sourceFile: 
    with codecs.open(targetFileName, "w", "utf-8") as targetFile: 
     while True: 
      contents = sourceFile.read(BLOCKSIZE) 
      if not contents: 
       break 
      targetFile.write(contents) 
2

Invece di lettore csv Io uso file letto e funzione split per la stringa:

lines = open(input_file,'rb') 

for line_all in lines: 

    line=line_all.replace('\x00', '').split(";") 
1

Questo è successo a me quando ho creato un file CSV con OpenOffice Calc. Non è successo quando ho creato il file CSV nel mio editor di testo, anche se in seguito l'ho modificato con Calc.

Ho risolto il mio problema copiando nell'editor di testo i dati del mio file creato da Calc in un nuovo file creato da un editor.

1

Ho avuto lo stesso problema aprendo un CSV prodotto da un servizio web che ha inserito byte NULL in intestazioni vuote. Ho fatto quello che segue per il file:

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile: 
    data = myfile.read() 
    # clean file first if dirty 
    if data.count('\x00'): 
     print 'Cleaning...' 
     with codecs.open('my.csv.tmp', 'w', 'utf-8') as of: 
      for line in data: 
       of.write(line.replace('\x00', '')) 

     shutil.move('my.csv.tmp', 'my.csv') 

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile: 
    myreader = csv.reader(myfile, delimiter=',') 
    # Continue with your business logic here... 

responsabilità: Essere consapevoli che questo sovrascrive i dati originali. Assicurati di averne una copia di backup. Sei stato avvertito!

0

Per tutti quei 'ru' odiano FileMode: Ho appena provato ad aprire un file CSV da una macchina Windows su un Mac con il fileMode 'rb' e ho ottenuto questo errore dal modulo csv:

Error: new-line character seen in unquoted field - do you need to 
open the file in universal-newline mode? 

L'apertura del file in modalità 'rU' funziona correttamente. Adoro la modalità newline universale: mi risparmia tanto fastidio.

15

Leggendolo come UTF-16 era anche il mio problema.

Ecco il mio codice che ha finito per lavorare:

f=codecs.open(location,"rb","utf-16") 
csvread=csv.reader(f,delimiter='\t') 
csvread.next() 
for row in csvread: 
    print row 

Dove posizione è la directory del file CSV.

0

L'ho riscontrato quando si utilizzava scrapy e si scaricava un file csv zippato senza avere un middleware corretto per decomprimere il corpo della risposta prima di passarlo al csvreader. Quindi il file non era realmente un file CSV e ha gettato l'errore line contains NULL byte di conseguenza.

4

Si potrebbe semplicemente inline un generatore per filtrare i valori nulli se si vuole far finta che non esistano. Ovviamente questo presuppone che i byte null non facciano realmente parte della codifica e siano in realtà una sorta di artefatto o bug errati.

with open(filepath, "rb") as f: 
    reader = csv.reader((line.replace('\0','') for line in f)) 

    try: 
     for row in reader: 
      print 'Row read successfully!', row 
    except csv.Error, e: 
     sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e)) 
8
data_initial = open("staff.csv", "rb") 
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",") 

questo funziona per me.

+0

Risolto per il mio caso, null erano i valori '\ 0'. Grazie. –

-1

Un caso è che - Se il file CSV contiene righe vuote, questo errore potrebbe apparire. Controlla che la riga sia necessaria prima di procedere alla scrittura o alla lettura.

for row in csvreader: 
     if (row):  
      do something 

Ho risolto il problema aggiungendo questo controllo nel codice.

Problemi correlati