"Zeile enthält NULL-Byte" im CSV-Reader (Python)

84

Ich versuche, ein Programm zu schreiben, das eine CSV-Datei (input.csv) betrachtet und nur die Zeilen neu schreibt, die mit einem bestimmten Element (korrigiert.csv) beginnen, wie in einer Textdatei (output.txt) aufgeführt.

So sieht mein Programm jetzt aus:

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)

Leider bekomme ich diesen Fehler immer wieder und ich habe keine Ahnung, worum es geht.

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

Wir danken allen Menschen hier , um mich an diesen Punkt zu bringen.

James Roseman
quelle
Nur eine Vermutung, aber es hört sich so an, als ob Ihre input.csv-Datei eine leere Zeile enthält (mebe am Ende?). Versuchen Sie, in der Datei csvParser.py nach diesem Ausnahmetext zu suchen.
Sam Axe
Ich habe gerade die Datei input.csv durchgesehen und alle Leerzeichen entfernt ... immer noch kein Glück (gleicher Fehler).
James Roseman
Um die Zeilennummer genau zu bestimmen, schlage ich vor, dass Sie eine Zählervariable einführen und innerhalb der for row in readerSchleife erhöhen.
Codeape
Ich bin mir nicht sicher, wie ich das machen soll, wenn das Programm selbst nicht ausgeführt wird. Ich habe versucht, einen Zähler hinzuzufügen, und es wurde nichts anderes angezeigt, nur der gleiche Traceback-Fehler.
James Roseman
4
Haben Sie ein NULL-Byte in Ihrer CSV-Datei? open('input.csv').read().index('\0')Wenn Sie dies tun, erhalten Sie den Versatz des ersten.
Retracile

Antworten:

65

Ich habe ein ähnliches Problem mit einer einfacheren Lösung gelöst:

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

Der Schlüssel war die Verwendung des Codecs-Moduls, um die Datei mit der UTF-16-Codierung zu öffnen. Es gibt viel mehr Codierungen. Überprüfen Sie die Dokumentation .

K. David C.
quelle
4
Ich hatte das gleiche Problem mit einer aus LibreOffice erstellten CSV-Datei, die ursprünglich aus einer Excel-XLS-Datei geöffnet wurde. Aus irgendeinem Grund hatte LibreOffice die CSV-Datei als UTF-16 gespeichert. Sie können anhand der ersten 2 Bytes der Datei erkennen, ob es sich um FF FE handelt. Dies ist ein guter Indikator dafür, dass es sich um UTF-16 handelt
Tom Dalton,
4
Beachten Sie, dass wenn Ihre Datei UTF-16-Daten enthält, die außerhalb des ASCII-Bereichs csv.reader() liegen, diese nicht verarbeitet werden können und Sie UnicodeEncodeErrorstattdessen s erhalten.
Martijn Pieters
5
Dies führte nur dazu, dass ein anderer Fehler ausgelöst wurdeUnicodeError: UTF-16 stream does not start with BOM
Cerin
In meinem Fall war es 'utf-16le'.
Paweł Szczur
68

Ich vermute, Sie haben ein NUL-Byte in input.csv. Sie können das mit testen

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

wenn Sie tun,

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

kann Sie um das herum bringen. Oder es zeigt an, dass Sie utf16 oder etwas 'Interessantes' in der CSV-Datei haben.

retracile
quelle
5
+1 beim Finden von NULL-Bytes in der Datei ... leider liest sich meine 'korrigierte.csv'-Datei jetzt auf Japanisch ...
James Roseman
Klingt so, als ob Ihre CSV-Datei nicht in ASCII vorliegt. Ich denke, für weitere Hilfe sind etwas mehr Informationen über den tatsächlichen Inhalt Ihrer CSV erforderlich. Haben Sie versucht, es in einem Texteditor wie vim oder notepad zu öffnen? Oder laufen file input.csv, um den Dateityp zu identifizieren?
Retracile
Ich habe es im Editor geöffnet und es sieht gut aus. Wie soll eine CSV aussehen? Es liest sich genauso wie bei Google Analytics, jedoch mit großen Registerkarten zwischen den Daten.
James Roseman
Verdammt ... gibt es eine Möglichkeit, die Tabulatoren durch Kommas zu ersetzen und mit dem Python-Programm zu arbeiten?
James Roseman
1
Wenn Ihre CSV tabulatorgetrennt ist, müssen Sie Folgendes angeben : reader = csv.reader(mycsv, delimiter='\t'). Ich stelle mir vor, dass der CSV-Reader Ihre gesamte Datei verschlingt, nach Kommas sucht und bis zur EOF gelangt. Aber Sie haben definitiv ein Codierungsproblem. Sie müssen die Codierung beim Öffnen der Datei angeben.
Steven Rumbalski
11

Wenn Sie die Nullen durch etwas ersetzen möchten, können Sie dies tun:

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

r = csv.reader(fix_nulls(open(...)))
Claudiu
quelle
2
Das Ersetzen von null durch ein Leerzeichen ist keine gute Wahl. Arbeitete für mich, um durch eine leere Zeichenfolge zu ersetzen
Marcelo Assis
10

Sie können einfach einen Generator einbinden, um die Nullwerte herauszufiltern, wenn Sie so tun möchten, als ob sie nicht existieren. Dies setzt natürlich voraus, dass die Null-Bytes nicht wirklich Teil der Codierung sind und wirklich eine Art fehlerhaftes Artefakt oder Fehler sind.

Siehe (line.replace('\0','') for line in f)unten, außerdem möchten Sie diese Datei wahrscheinlich im Modus öffnen 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)
woot
quelle
Vielen Dank! Dies funktionierte für die NC-Wahlergebnisdateien, die tatsächlich (!) Ein Null-Byte anstelle eines "0" -Bytes in einer Spalte verwenden. Siehe dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb
7

Hier erfahren Sie, in welcher Leitung das Problem liegt.

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

Vielleicht wäre dies von daniweb hilfreich:

Beim Lesen aus einer CSV-Datei wird folgende Fehlermeldung angezeigt: "Runtime Error! Zeile enthält NULL-Byte". Irgendeine Idee über die Grundursache dieses Fehlers?

...

Ok, ich habe es verstanden und dachte, ich würde die Lösung veröffentlichen. Einfach noch Kummer verursacht ... Die verwendete Datei wurde in einem XLS-Format anstelle einer CSV-Datei gespeichert. Dies wurde nicht abgefangen, da der Dateiname selbst die Erweiterung CSV hatte, während der Typ noch XLS war

Steven Rumbalski
quelle
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. Dann verschluckt es sich in der ersten Zeile. Führen Sie dies aus und posten Sie, was Sie sehen:print(open('input.csv', 'r').readlines()[0])
Steven Rumbalski
Etwas Funky ... aber es läuft. ÿþ/<Das ist alles, was es einfügen würde (es sind hauptsächlich Blöcke und Zahlen)
James Roseman
1
Vielleicht ist Ihre CSV nicht wirklich eine CSV. Siehe die zweite Hälfte meiner Antwort.
Steven Rumbalski
Oh, schieß, das könnte es sein, wie könnte ich das beheben? Ich habe es auch direkt aus Google Analytics gespeichert ...
James Roseman
2

Ein kniffliger Weg:

Wenn Sie sich unter Lunux entwickeln, können Sie die gesamte Kraft von sed nutzen :

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)    

Die effizienteste Lösung für große Dateien.

Überprüft auf Python3, Kubuntu

SergO
quelle
1

Ich habe dieses Problem kürzlich behoben und in meinem Fall war es eine komprimierte Datei, die ich lesen wollte. Überprüfen Sie zuerst das Dateiformat. Überprüfen Sie dann, ob der Inhalt der Erweiterung entspricht.

Daniel Lee
quelle
1

Die Umwandlung meiner Linux-Umgebung in eine saubere, vollständige UTF-8-Umgebung war für mich der Trick. Versuchen Sie Folgendes in Ihrer Befehlszeile:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
Philippe Oger
quelle
Für mich löste auch der Wechsel zu UTF-8 das Problem. Unter Windows habe ich Notepad ++ verwendet, um das Format von UTF16 auf UTF8 zu ändern. Ich öffnete dann die Datei mit libreoffice calc und löschte zusätzliche Zeilen usw.
Yuval Harpaz
1

Dies ist seit langem geklärt, aber ich bin auf diese Antwort gestoßen, weil beim Lesen einer CSV, die als Trainingsdaten in Keras und TensorFlow verarbeitet werden soll, ein unerwarteter Fehler aufgetreten ist.

In meinem Fall war das Problem viel einfacher und es lohnt sich, sich dessen bewusst zu sein. Die in der CSV erzeugten Daten waren nicht konsistent, was dazu führte, dass einige Spalten vollständig fehlten, was diesen Fehler ebenfalls zu verursachen scheint.

Die Lektion: Wenn Sie diesen Fehler sehen, überprüfen Sie, ob Ihre Daten so aussehen, wie Sie denken, dass dies der Fall ist!

David Hoelzer
quelle