"La línea contiene un byte NULL" en el lector de CSV (Python)

84

Estoy tratando de escribir un programa que busque en un archivo .CSV (input.csv) y reescriba solo las filas que comienzan con un determinado elemento (corrected.csv), como se enumeran en un archivo de texto (output.txt).

Así es como se ve mi programa en este 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)

Desafortunadamente, sigo recibiendo este error y no tengo ni idea de qué se trata.

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

Agradezco a toda la gente que está aquí por haberme llegado a este punto.

James Roseman
fuente
Solo una suposición, pero parece que su archivo input.csv contiene una línea en blanco (¿tal vez al final?). Intente buscar en el archivo csvParser.py ese texto de excepción.
Sam Axe
De hecho, revisé el archivo input.csv y me deshice de todos los espacios en blanco ... todavía no tuve suerte (el mismo error).
James Roseman
Para señalar el número de línea, le sugiero que introduzca una variable de contador y la incremente dentro del for row in readerciclo.
Codeape
No estoy seguro de cómo se supone que debo hacer eso cuando el programa en sí no se ejecuta. Intenté agregar un contador y no apareció nada diferente, solo el mismo error de rastreo.
James Roseman
4
¿Tiene un byte NULL en su .csv? open('input.csv').read().index('\0')le dará el desplazamiento del primero si lo hace.
retracile

Respuestas:

66

Resolví un problema similar con una solución más sencilla:

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

La clave fue usar el módulo de códecs para abrir el archivo con la codificación UTF-16, hay muchas más codificaciones, consulte la documentación .

K. David C.
fuente
4
Tuve este mismo problema con un archivo CSV creado a partir de LibreOffice, que se había abierto originalmente desde un archivo .xls de Excel. Por alguna razón, LibreOffice había guardado el archivo CSV como UTF-16. Puede saber al mirar los primeros 2 bytes del archivo, si es FF FE, entonces es un buen indicador de que es UTF-16
Tom Dalton
4
Tenga en cuenta que si su archivo contiene datos UTF-16 que están fuera del rango ASCII csv.reader() , no podrá manejarlos y obtendrá UnicodeEncodeErrors en su lugar.
Martijn Pieters
6
Esto sólo provocó un error diferente a ser elevado,UnicodeError: UTF-16 stream does not start with BOM
Cerin
En mi caso lo fue 'utf-16le'.
Paweł Szczur
69

Supongo que tiene un byte NUL en input.csv. Puedes probar eso con

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

si lo haces,

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

puede ayudarte a evitar eso. O puede indicar que tiene utf16 o algo 'interesante' en el archivo .csv.

retraciliar
fuente
5
+1 al encontrar bytes NULL en el archivo ... desafortunadamente ahora mi archivo 'corrected.csv' ahora se lee en japonés ...
James Roseman
Parece que su .csv no está en ascii. Creo que la ayuda adicional requerirá un poco más de información sobre el contenido real de su .csv. ¿Ha intentado abrirlo en un editor de texto como vim o notepad? ¿O corriendo file input.csvpara identificar el tipo de archivo?
retracile
Lo abrí en el Bloc de notas y se ve bien. ¿Cómo debería verse un csv? Se lee igual que en Google Analytics, pero con pestañas enormes entre los datos.
James Roseman
Maldita sea ... ¿hay alguna forma de reemplazar las pestañas con comas y hacer que funcione con el programa Python?
James Roseman
1
Si su csv está delimitada pestaña es necesario especificar de modo: reader = csv.reader(mycsv, delimiter='\t'). Imagino que el lector de csv está engullendo todo su archivo buscando las comas y llegando hasta EOF. Pero definitivamente tienes un problema de codificación. Debe especificar la codificación al abrir el archivo.
Steven Rumbalski
11

Si desea reemplazar los nulos con algo, puede hacer esto:

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

r = csv.reader(fix_nulls(open(...)))
Claudiu
fuente
2
Reemplazar nulo con un espacio no será una buena opción. Me funcionó para reemplazar con una cadena vacía
Marcelo Assis
Tengo una pregunta sobre cómo ha utilizado el rendimiento. Dado que esto está en un bucle, ¿significa que todavía leerá el archivo línea por línea o lo cargará en la memoria de una vez?
mnsr
10

Podría simplemente incorporar un generador para filtrar los valores nulos si desea fingir que no existen. Por supuesto, esto supone que los bytes nulos no son realmente parte de la codificación y realmente son algún tipo de artefacto o error erróneo.

Vea lo (line.replace('\0','') for line in f)siguiente, también probablemente querrá abrir ese archivo usando el modo 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
fuente
¡Gracias! Esto funcionó para los archivos de resultados electorales de NC, que de hecho (!) Usan un byte nulo en lugar de un byte "0" en una columna. Ver dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb
7

Esto le dirá qué línea es el 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

Quizás esto de daniweb sería útil:

Recibo este error cuando leo de un archivo csv: "¡Error en tiempo de ejecución! La línea contiene un byte NULL". ¿Alguna idea sobre la causa raíz de este error?

...

Ok, lo entendí y pensé en publicar la solución. Simplemente todavía me causó dolor ... El archivo usado se guardó en formato .xls en lugar de .csv No entendí esto porque el nombre del archivo en sí tenía la extensión .csv mientras el tipo aún era .xls

Steven Rumbalski
fuente
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
Okay. Entonces se ahoga en la primera línea. Ejecute esto y publique lo que ve:print(open('input.csv', 'r').readlines()[0])
Steven Rumbalski
Algo raro ... pero está funcionando. ÿþ/<Eso es todo lo que pegaría (principalmente bloques y números)
James Roseman
1
Quizás su csv no sea realmente un csv. Vea la segunda mitad de mi respuesta.
Steven Rumbalski
Oh, dispara, eso podría ser completamente, ¿cómo puedo arreglar esto? También lo guardé directamente de Google Analytics ...
James Roseman
2

Una forma complicada:

Si desarrolla bajo Lunux, puede usar todo el poder de 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 solución más eficaz para archivos de gran tamaño.

Comprobado para Python3, Kubuntu

SergO
fuente
1

Recientemente solucioné este problema y, en mi caso, era un archivo comprimido que estaba tratando de leer. Primero verifique el formato de archivo. Luego verifique que el contenido sea a lo que se refiere la extensión.

Daniel Lee
fuente
1

Convertir mi entorno Linux en un entorno UTF-8 completo y limpio fue el truco para mí. Intente lo siguiente en su línea de comando:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
Philippe Oger
fuente
para mí también el cambio a UTF-8 resolvió el problema. En Windows utilicé Notepad ++ para cambiar el formato de UTF16 a UTF8. Luego abrí el archivo con libreoffice calc y
borré
1

Esto se resolvió hace mucho tiempo, pero encontré esta respuesta porque estaba experimentando un error inesperado mientras leía un CSV para procesar como datos de entrenamiento en Keras y TensorFlow.

En mi caso, la cuestión era mucho más sencilla y merece la pena ser consciente. Los datos que se producían en el CSV no eran consistentes, lo que provocaba que algunas columnas faltaran por completo, lo que parece terminar arrojando este error también.

La lección: si ves este error, verifica que tus datos se vean como crees.

David Hoelzer
fuente