Kesalahan CSV Python: baris berisi byte NULL


102

Saya sedang mengerjakan beberapa file CSV, dengan kode berikut:

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

Dan satu file menimbulkan kesalahan ini:

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

Apa yang dapat saya? Google tampaknya menyarankan bahwa itu mungkin file Excel yang disimpan sebagai .csv secara tidak benar. Apakah ada cara untuk mengatasi masalah ini dengan Python?

== UPDATE ==

Mengikuti komentar @ JohnMachin di bawah ini, saya mencoba menambahkan baris ini ke skrip saya:

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

Dan inilah output yang saya dapatkan:

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

Jadi file tersebut memang mengandung byte NUL.


Seperti apa od -cbaris pertama itu?
Ignacio Vazquez-Abrams

kueri apa yang harus saya jalankan, seperti cat my.csv | od -c | lebih? dengan itu saya mendapatkan: 0000000 D epartment F amil
AP257

Bagaimana CSV dibuat? Dari excel, Anda mungkin bisa mencoba dialek. Jika tidak, lihat katakan: stackoverflow.com/questions/2753022/…
dr jimbob

Terima kasih. Ini bukan CSV saya, dan sayangnya saya tidak memiliki kekuatan untuk mengubahnya. Saya pikir itu telah dibuat sebagai Excel dan disimpan sebagai CSV (boo). Sebuah dialek terdengar seperti ide yang bagus - Saya akan mencobanya!
AP257

Jika itu benar-benar disimpan sebagai CSV, itu seharusnya berfungsi. Satu hal yang terkadang saya temukan adalah file TSV (dipisahkan tab) yang menyamar sebagai CSV, jadi Anda dapat mencoba menyetel pembatas '\ t'. Jika telah disimpan sebagai file Excel, dan ekstensi diubah menjadi CSV, tidak ada dialek yang akan berfungsi. Saya pikir satu-satunya pilihan Anda dalam hal ini adalah menggunakan Excel untuk menyimpan salinan sebagai CSV yang tepat.
Thomas K

Jawaban:


104

Seperti yang dikatakan @ S. Lott, Anda harus membuka file Anda dalam mode 'rb', bukan mode 'rU'. Namun itu mungkin TIDAK menyebabkan masalah Anda saat ini. Sejauh yang saya tahu, menggunakan mode 'rU' akan mengacaukan Anda jika ada yang tertanam \rdi data, tetapi tidak menyebabkan drama lain. Saya juga mencatat bahwa Anda memiliki beberapa file (semua dibuka dengan 'rU' ??) tetapi hanya satu yang menyebabkan masalah.

Jika modul csv mengatakan bahwa Anda memiliki byte "NULL" (pesan konyol, harus "NUL") di file Anda, maka Anda perlu memeriksa apa yang ada di file Anda. Saya menyarankan Anda melakukan ini bahkan jika menggunakan 'rb' membuat masalah hilang.

repr()adalah (atau ingin menjadi) teman debugging Anda. Ini akan menunjukkan dengan jelas apa yang Anda miliki, dalam mode platform independen (yang berguna untuk pembantu yang tidak menyadari apa yang odsedang atau dilakukan). Melakukan hal ini:

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

dan dengan hati-hati salin / tempel (jangan ketik ulang) hasilnya ke dalam edit pertanyaan Anda (bukan menjadi komentar).

Perhatikan juga bahwa jika file benar-benar cerdik mis. Tidak ada \ r atau \ n dalam jarak yang wajar dari awal file, nomor baris yang dilaporkan oleh reader.line_numakan (tidak membantu) 1. Temukan di mana yang pertama \x00(jika ada) dengan melakukan

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

dan pastikan bahwa Anda membuang setidaknya banyak byte dengan repr atau od.

Apa yang data.count('\x00')memberitahumu? Jika ada banyak, Anda mungkin ingin melakukan sesuatu seperti

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

sehingga Anda dapat melihat byte NUL dalam konteks.

Jika Anda dapat melihat \x00di output (atau \0di od -coutput Anda ), maka Anda pasti memiliki byte NUL di file, dan Anda perlu melakukan sesuatu seperti ini:

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

Omong-omong, apakah Anda sudah melihat file (termasuk beberapa baris terakhir) dengan editor teks? Apakah itu benar-benar terlihat seperti file CSV yang wajar seperti file lainnya (tanpa pengecualian "NULL byte")?


Terima kasih banyak atas bantuan yang sangat mendetail ini. Ada banyak \ x00 karakter dalam file (lihat edit untuk pertanyaan) - ini aneh, karena dalam editor teks ini terlihat seperti file CSV yang masuk akal.
AP257

1
@ AP257: '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1adalah "tanda tangan" yang menunjukkan file Dokumen Gabungan OLE2 - misalnya file .XLS Excel 97-2003 . Saya menemukan "dalam editor teks, sepertinya file CSV yang masuk akal" benar - benar tidak dapat dipercaya . Anda pasti telah melihat file yang berbeda, file CSV yang valid, di folder lain atau di komputer lain atau di lain waktu. Perhatikan bahwa odkeluaran Anda bukan dari file XLS.
John Machin

8
@ AP257: Adakah alasan khusus Anda belum menerima jawaban ini?
John Machin

Berfungsi, tetapi harus memungkinkan dan menyenangkan dengan cepat dengan objek seperti file yang memfilter CSV dan dapat diteruskan ke csv.readersecara langsung.
gerrit

1
Tidak fo.write(data.replace('\x00', ''))seharusnya fo.write(data.replace(b'\x00', b''))? Python 3.6 di sini ...
Boern

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

Ini berhasil untuk saya.


Dipecahkan untuk kasus saya, null adalah nilai '\ 0'. Terima kasih.
Joab Mendes

19

Membacanya sebagai UTF-16 juga merupakan masalah saya.

Inilah kode saya yang akhirnya berfungsi:

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

Dimana lokasi adalah direktori file csv Anda.


13

Saya mengalami masalah ini juga. Menggunakan csvmodul Python , saya mencoba membaca file XLS yang dibuat di MS Excel dan mengalami NULL bytekesalahan yang Anda dapatkan. Saya melihat sekeliling dan menemukan modul Python xlrd untuk membaca dan memformat data dari file spreadsheet MS Excel. Dengan xlrdmodul ini, saya tidak hanya dapat membaca file dengan benar, tetapi saya juga dapat mengakses banyak bagian file dengan cara yang tidak dapat saya lakukan sebelumnya.

Saya pikir itu mungkin membantu Anda.


7
Terima kasih telah menunjukkan modul itu. Yang cukup menarik, saya pergi untuk mendownloadnya dan melihat bahwa penulisnya tidak lain adalah @John_Machin yang juga merupakan komentar teratas untuk pertanyaan ini.
Evan

11

Mengonversi pengkodean file sumber dari UTF-16 ke UTF-8 memecahkan masalah saya.

Bagaimana cara mengonversi file ke utf-8 dengan 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)

7

Anda bisa membuat generator sebaris untuk menyaring nilai null jika Anda ingin berpura-pura tidak ada. Tentu saja ini mengasumsikan byte nol sebenarnya bukan bagian dari pengkodean dan sebenarnya adalah semacam artefak atau bug yang salah.

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

2

Mengapa kau melakukan ini?

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

Dokumennya cukup jelas bahwa Anda harus melakukan ini:

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

Modusnya harus "rb" untuk membaca.

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

Jika csvfile adalah sebuah objek file, itu harus dibuka dengan tanda 'b' pada platform yang membuat perbedaan.


@ AP257: "Tidak membantu"? Artinya apa? Ada pesan kesalahan khusus?
S. Lott

1
@ S. Lott: Berarti dia mendapat jawaban yang sama seperti sebelumnya. Kenyataannya adalah dia berurusan dengan file bunglon atau shapeshifter ... ketika dia membuangnya odatau melihatnya di editor teks, itu terlihat seperti file CSV yang normal. Namun ketika dia membuang beberapa byte pertama dengan Python repr (), itu menjadi seperti file .XLS Excel (yang telah diganti namanya menjadi memiliki ekstensi CSV).
John Machin

@ John Machin: "file .XLS Excel (yang telah diubah namanya menjadi ekstensi CSV" Masuk akal bahwa file tersebut tidak dapat diproses sama sekali.
S.Lott

1
@ S.Lott: Dengan konten tersebut, masuk akal bahwa modul csv tidak dapat memprosesnya; namun modul xlrd dapat memprosesnya. Seharusnya, tidak ada modul yang menyimpulkan apapun dari nama file input, jika memang inputnya adalah file dengan nama.
John Machin

1
@ John Machin: "tidak ada modul yang menyimpulkan apa pun dari nama file input". Benar. Kerangka aplikasi saya bergantung pada fakta itu. Kami tidak percaya nama file berarti apa-apa, karena orang membuat kesalahan ("berbohong"). Jadi kita harus memeriksa banyak alternatif hingga satu klik.
S. Lott


2

Alih-alih pembaca csv, saya menggunakan file baca dan fungsi split untuk string:

lines = open(input_file,'rb') 

for line_all in lines:

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

1

Saya mendapat kesalahan yang sama. Menyimpan file dalam UTF-8 dan berhasil.


1
Anda mungkin mendapatkan pesan kesalahan yang sama, tetapi penyebabnya akan berbeda - Anda mungkin menyimpannya pada awalnya sebagai UTF-16 (yang oleh Notepad disebut "Unicode").
John Machin

1

Ini terjadi pada saya ketika saya membuat file CSV dengan OpenOffice Calc. Itu tidak terjadi ketika saya membuat file CSV di editor teks saya, bahkan jika saya kemudian mengeditnya dengan Calc.

Saya memecahkan masalah saya dengan menyalin-menempel di editor teks saya data dari file yang saya buat Calc ke file yang dibuat editor baru.


1

Saya memiliki masalah yang sama membuka CSV yang dihasilkan dari layanan web yang memasukkan byte NULL di header kosong. Saya melakukan hal berikut untuk membersihkan 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...

Penafian: Ketahuilah bahwa ini menimpa data asli Anda. Pastikan Anda memiliki salinan cadangannya. Anda telah diperingatkan!


0

Untuk semua pembenci filemode 'rU': Saya baru saja mencoba membuka file CSV dari mesin Windows di Mac dengan filemode 'rb' dan saya mendapatkan kesalahan ini dari modul csv:

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

Membuka file dalam mode 'rU' berfungsi dengan baik. Saya suka mode universal-newline - ini menghemat banyak kerumitan.


0

Saya mengalami ini saat menggunakan scrapy dan mengambil file csvfile yang sudah di-zip tanpa middleware yang benar untuk mengekstrak badan respons sebelum menyerahkannya ke csvreader. Karenanya file tersebut sebenarnya bukan file csv dan memberikan line contains NULL bytekesalahan yang sesuai.


0

Sudahkah Anda mencoba menggunakan gzip.open?

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

Saya mencoba membuka file yang telah dikompresi tetapi memiliki ekstensi '.csv', bukan 'csv.gz'. Kesalahan ini terus muncul sampai saya menggunakan gzip.open


-1

Salah satu kasusnya adalah - Jika file CSV berisi baris kosong, kesalahan ini mungkin muncul. Memeriksa baris diperlukan sebelum kita melanjutkan untuk menulis atau membaca.

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

Saya memecahkan masalah saya dengan menambahkan cek ini di kode.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.