web-dev-qa-db-fra.com

Erreur CSV Python: la ligne contient l'octet NULL

Je travaille avec des fichiers CSV, avec le code suivant:

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))

Et un fichier jette cette erreur: 

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

Que puis-je faire? Google semble suggérer qu'il peut s'agir d'un fichier Excel enregistré au format .csv de manière incorrecte. Est-il possible de résoudre ce problème en Python?

== UPDATE ==

Après le commentaire de @ JohnMachin ci-dessous, j'ai essayé d'ajouter ces lignes à mon 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')

Et voici le résultat obtenu: 

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

Le fichier contient donc bien des octets NUL. 

83
AP257

Comme @ S.Lott le dit, vous devriez ouvrir vos fichiers en mode "rb" et non en mode "rU". Cependant cela ne cause PAS votre problème actuel. Autant que je sache, l'utilisation du mode 'rU' vous dérangerait s'il y avait un \r incorporé dans les données, mais ne causerait pas d'autres drames. Je note également que vous avez plusieurs fichiers (tous ouverts avec 'rU' ??) mais qu'un seul cause un problème.

Si le module csv indique que vous avez un octet "NULL" (message idiot, devrait être "NUL") dans votre fichier, vous devez vérifier ce qui est dans votre fichier. Je suggérerais que vous fassiez cela même si utiliser «rb» fait disparaître le problème.

repr() est (ou veut être) votre ami de débogage. Cela montrera sans ambiguïté ce que vous avez, d’une manière indépendante de la plate-forme (ce qui est utile pour les assistants qui ne savent pas ce que od est ou fait). Faire ceci:

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

et copiez/collez soigneusement (ne retapez pas) le résultat dans une édition de votre question (pas dans un commentaire).

Notez également que si le fichier est vraiment louche, par exemple. non\r ou\n à une distance raisonnable du début du fichier, le numéro de ligne indiqué par reader.line_num sera (sans aide) 1. Recherchez où se trouve le premier \x00 (le cas échéant)

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

et assurez-vous de supprimer au moins autant d'octets avec repr ou od.

Que vous dit data.count('\x00')? S'il y en a beaucoup, vous voudrez peut-être faire quelque chose comme

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

afin que vous puissiez voir les octets NUL dans leur contexte.

Si vous pouvez voir \x00 dans la sortie (ou \0 dans votre sortie od -c), alors vous avez certainement NUL octet (s) dans le fichier et vous devrez faire quelque chose comme ceci:

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

Au fait, avez-vous regardé le fichier (y compris les dernières lignes) avec un éditeur de texte? Cela ressemble-t-il réellement à un fichier CSV raisonnable comme les autres fichiers (sans exception "octet NULL")?

96
John Machin

Le lire comme UTF-16 était aussi mon problème.

Voici mon code qui a fini par fonctionner:

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

Où location est le répertoire de votre fichier csv.

17
User
data_initial = open("staff.csv", "rb")
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",")

Cela fonctionne pour moi.

14
double

Je suis tombé sur ce problème aussi. À l’aide du module csv de Python, j’essayais de lire un fichier XLS créé dans MS Excel et de l’erreur NULL byte que vous obteniez. J'ai regardé autour de moi et trouvé le module xlrd Python permettant de lire et de formater des données à partir de fichiers de feuille de calcul MS Excel. Avec le module xlrd, je ne suis pas seulement capable de lire le fichier correctement, mais je peux également accéder à de nombreuses parties différentes du fichier comme je ne pouvais pas le faire auparavant.

Je pensais que cela pourrait vous aider.

12
ayaz

La conversion de l'encodage du fichier source d'UTF-16 à UTF-8 résout mon problème.

Comment convertir un fichier en utf-8 en 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)
10
Patrick Halley

Vous pouvez simplement inclure un générateur pour filtrer les valeurs NULL si vous voulez prétendre qu'elles n'existent pas. Bien sûr, cela suppose que les octets nuls ne font pas vraiment partie de l'encodage et constituent en réalité une sorte d'artefact ou de bogue erroné.

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))
6
woot

Au lieu du lecteur csv, j’utilise le fichier read et la fonction split pour string:

lines = open(input_file,'rb') 

for line_all in lines:

    line=line_all.replace('\x00', '').split(";")
2
Nico The Brush

Pourquoi fais-tu ça?

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

Les docs sont assez clairs pour dire que vous devez faire ceci:

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

Le mode doit être "rb" pour être lu.

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

Si csvfile est un objet fichier, vous devez l’ouvrir avec le drapeau «b» sur les plates-formes où cela fait une différence. 

2
S.Lott

apparemment c'est un fichier XLS et non un fichier CSV comme http://www.garykessler.net/library/file_sigs.html confirm

2
Xavier Combelle

Cela m'est arrivé lorsque j'ai créé un fichier CSV avec OpenOffice Calc. Cela ne s'est pas produit lorsque j'ai créé le fichier CSV dans mon éditeur de texte, même si je l'ai édité ultérieurement avec Calc.

J'ai résolu mon problème en copiant dans mon éditeur de texte les données de mon fichier créé par Calc dans un nouveau fichier créé par l'éditeur.

1
user1990371

J'ai eu le même problème lors de l'ouverture d'un fichier CSV produit à partir d'un service Web dans lequel des octets NULL étaient insérés dans des en-têtes vides. J'ai fait ce qui suit pour nettoyer le fichier:

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...

Clause de non-responsabilité: Soyez conscient que cela écrase vos données d'origine. Assurez-vous d'avoir une copie de sauvegarde. Tu étais prévenu!

1
Matthias Kuhn

J'ai eu la même erreur. Enregistré le fichier dans UTF-8 et cela a fonctionné.

1
mikaiscute

J'ai rencontré ce problème lors de l'utilisation de scrapy et de la récupération d'un fichier csvf compressé sans disposer d'un middleware correct permettant de décompresser le corps de la réponse avant de le remettre au csvreader. Par conséquent, le fichier n’était pas vraiment un fichier csv et renvoyait l’erreur line contains NULL byte en conséquence.

0
Gesias

Pour tous ces détracteurs de «fil» en mode «rU»: j'ai juste essayé d'ouvrir un fichier CSV à partir d'une machine Windows sur un Mac avec le mode de fichier «rb» et j'ai obtenu cette erreur du module csv:

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

Ouvrir le fichier en mode 'rU' fonctionne bien. J'adore le mode newline universel - cela me épargne beaucoup de tracas.

0
Bill Gross

Avez-vous essayé d'utiliser gzip.open?

with gzip.open('my.csv', 'rb') as data_file:

J'essayais d'ouvrir un fichier compressé mais portant l'extension ".csv" au lieu de "csv.gz". Cette erreur continuait à apparaître jusqu'à ce que j'utilise gzip.open

0