"La riga contiene byte NULL" nel lettore CSV (Python)


86

Sto cercando di scrivere un programma che guardi un file .CSV (input.csv) e riscrive solo le righe che iniziano con un determinato elemento (corrected.csv), come elencato in un file di testo (output.txt).

Questo è l'aspetto del mio programma in questo momento:

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'r') as mycsv:
        reader = csv.reader(mycsv)
        for row in reader:
            if row[0] not in lines:
                writer.writerow(row)

Sfortunatamente, continuo a ricevere questo errore e non ho idea di cosa si tratti.

Traceback (most recent call last):
  File "C:\Python32\Sample Program\csvParser.py", line 12, in <module>
    for row in reader:
_csv.Error: line contains NULL byte

Ringrazio tutte le persone qui anche per avermi portato a questo punto.


È solo una supposizione, ma sembra che il tuo file input.csv contenga una riga vuota (mebe alla fine?). Prova a cercare nel file csvParser.py quel testo di eccezione.
Sam Axe

In realtà ho appena esaminato il file input.csv e mi sono sbarazzato di tutti gli spazi vuoti ... ancora senza fortuna (stesso errore).
James Roseman

Per individuare il numero di riga, suggerisco di introdurre una variabile counter e di incrementarla all'interno del for row in readerciclo.
codeape

Non sono sicuro di come dovrei farlo quando il programma stesso non verrà eseguito. Ho provato ad aggiungere un contatore e non è emerso nulla di diverso, solo lo stesso errore di traceback.
James Roseman

4
Hai un byte NULL nel tuo .csv? open('input.csv').read().index('\0')ti darà l'offset del primo se lo fai.
retracile

Risposte:


69

Ho risolto un problema simile con una soluzione più semplice:

import codecs
csvReader = csv.reader(codecs.open('file.csv', 'rU', 'utf-16'))

La chiave era usare il modulo codecs per aprire il file con la codifica UTF-16, ci sono molte più codifiche, controlla la documentazione .


4
Ho avuto lo stesso problema con un file CSV creato da LibreOffice, che era stato originariamente aperto da un file .xls di Excel. Per qualche motivo, LibreOffice aveva salvato il file CSV come UTF-16. Puoi dirlo guardando i primi 2 byte del file, se è FF FE, allora è un buon indicatore che è UTF-16
Tom Dalton

4
Nota che se il tuo file contiene dati UTF-16 che sono al di fuori dell'intervallo ASCII csv.reader() non sarà in grado di gestirlo e otterrai UnicodeEncodeErrorinvece s.
Martijn Pieters

7
Ciò ha solo causato la segnalazione di un errore diverso,UnicodeError: UTF-16 stream does not start with BOM
Cerin

Nel mio caso lo era 'utf-16le'.
Paweł Szczur

70

Immagino che tu abbia un byte NUL in input.csv. Puoi testarlo con

if '\0' in open('input.csv').read():
    print "you have null bytes in your input file"
else:
    print "you don't"

se fate,

reader = csv.reader(x.replace('\0', '') for x in mycsv)

potrebbe farti aggirare. Oppure potrebbe indicare che hai utf16 o qualcosa di "interessante" nel file .csv.


5
+1 sulla ricerca di byte NULL nel file ... sfortunatamente ora il mio file "corretto.csv" ora si legge in giapponese ...
James Roseman

Sembra che il tuo .csv non sia in ASCII. Penso che ulteriore aiuto richiederà un po 'più di informazioni sul contenuto effettivo del tuo .csv. Hai provato ad aprirlo in un editor di testo come vim o blocco note? O corri file input.csvper identificare il tipo di file?
retracile

L'ho aperto in Blocco note e sembra a posto. Come dovrebbe essere un csv? Si legge come su Google Analytics, ma con enormi schede tra i dati.
James Roseman

Dannazione ... c'è un modo per sostituire le tabulazioni con virgole e farlo funzionare con il programma Python?
James Roseman

1
Se il csv è delimitato da tabulazioni è necessario specificare in modo: reader = csv.reader(mycsv, delimiter='\t'). Immagino che il lettore CSV stia divorando l'intero file cercando le virgole e arrivando fino a EOF. Ma hai sicuramente un problema di codifica. È necessario specificare la codifica quando si apre il file.
Steven Rumbalski

15

Se vuoi sostituire i valori nulli con qualcosa, puoi farlo:

def fix_nulls(s):
    for line in s:
        yield line.replace('\0', ' ')

r = csv.reader(fix_nulls(open(...)))

2
Sostituire null con uno spazio non sarà una buona scelta. Ha funzionato per me per sostituire con una stringa vuota
Marcelo Assis

Ho una domanda su come hai utilizzato la resa. Dato che questo è in un ciclo, significa che leggerà ancora il file riga per riga o lo caricherà immediatamente nella memoria?
mnsr

10

Potresti semplicemente incorporare un generatore per filtrare i valori nulli se vuoi fingere che non esistano. Ovviamente questo presuppone che i byte nulli non facciano realmente parte della codifica e siano davvero una sorta di artefatto o bug errato.

Vedi (line.replace('\0','') for line in f)sotto, probabilmente vorrai anche aprire quel file usando la modalità rb.

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'rb') as mycsv:
        reader = csv.reader( (line.replace('\0','') for line in mycsv) )
        for row in reader:
            if row[0] not in lines:
                writer.writerow(row)

Grazie! Questo ha funzionato per i file dei risultati delle elezioni NC, che in effetti (!) Utilizzano un byte nullo al posto di un byte "0" in una colonna. Vedi dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb

7

Questo ti dirà quale linea è il problema.

import csv

lines = []
with open('output.txt','r') as f:
    for line in f.readlines():
        lines.append(line[:-1])

with open('corrected.csv','w') as correct:
    writer = csv.writer(correct, dialect = 'excel')
    with open('input.csv', 'r') as mycsv:
        reader = csv.reader(mycsv)
        try:
            for i, row in enumerate(reader):
                if row[0] not in lines:
                   writer.writerow(row)
        except csv.Error:
            print('csv choked on line %s' % (i+1))
            raise

Forse questo da daniweb sarebbe utile:

Ricevo questo errore durante la lettura da un file CSV: "Errore di runtime! La riga contiene byte NULL". Qualche idea sulla causa principale di questo errore?

...

Ok, ho capito e ho pensato di pubblicare la soluzione. Semplicemente ancora mi ha causato dolore ... Il file usato è stato salvato in un formato .xls invece di .csv Non ho capito perché il nome del file stesso aveva l'estensione .csv mentre il tipo era ancora .xls


1
Traceback (most recent call last): File "C:\Python32\Sample Program\csvParser.py", line 17, in <module> print ('csv choked on line %s' % (i+1)) NameError: name 'i' is not defined
James Roseman

Ok. Poi sta soffocando sulla primissima riga. Esegui questo e pubblica quello che vedi:print(open('input.csv', 'r').readlines()[0])
Steven Rumbalski

Qualcosa di strano ... ma sta funzionando. ÿþ/<È tutto ciò che incolla (sono principalmente blocchi e numeri)
James Roseman

1
Forse il tuo csv non è proprio un csv. Vedi la seconda metà della mia risposta.
Steven Rumbalski

Oh sparare potrebbe essere completamente, come potrei fare per risolverlo? L'ho salvato anche da Google Analytics ...
James Roseman

2

Un modo complicato:

Se sviluppi con Lunux, puoi utilizzare tutta la potenza di sed :

from subprocess import check_call, CalledProcessError

PATH_TO_FILE = '/home/user/some/path/to/file.csv'

try:
    check_call("sed -i -e 's|\\x0||g' {}".format(PATH_TO_FILE), shell=True)
except CalledProcessError as err:
    print(err)    

La soluzione più efficiente per file di grandi dimensioni.

Controllato per Python3, Kubuntu


1

Di recente ho risolto questo problema e nel mio caso si trattava di un file compresso che stavo cercando di leggere. Controlla prima il formato del file. Quindi controlla che i contenuti siano ciò a cui si riferisce l'estensione.


1

Trasformare il mio ambiente Linux in un ambiente UTF-8 completo e pulito ha reso il trucco per me. Prova quanto segue nella riga di comando:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

per me anche il passaggio a UTF-8 ha risolto il problema. Su Windows ho usato Notepad ++ per cambiare il formato da UTF16 a UTF8. Ho quindi aperto il file con libreoffice calc e cancellato le righe extra, ecc.
Yuval Harpaz,

1

Questo è risolto da tempo, ma mi sono imbattuto in questa risposta perché ho riscontrato un errore imprevisto durante la lettura di un CSV da elaborare come dati di addestramento in Keras e TensorFlow.

Nel mio caso, la questione era molto più semplice e vale la pena esserne consapevoli. I dati prodotti nel CSV non erano coerenti, risultando in alcune colonne completamente mancanti, il che sembra finire per generare anche questo errore.

La lezione: se visualizzi questo errore, verifica che i tuoi dati abbiano l'aspetto che pensi!


0

È molto semplice.

non creare un file CSV "crea un nuovo Excel" o salvarlo come ".csv" dalla finestra.

importa semplicemente il modulo csv, scrivi un file csv fittizio e poi incolla i tuoi dati in quello.

csv creato dal modulo python csv stesso non mostrerà più la codifica o l'errore di riga vuota.


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.