Python CSV hatası: satır NULL bayt içeriyor


102

Aşağıdaki kodla bazı CSV dosyalarıyla çalışıyorum:

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

Ve bir dosya bu hatayı veriyor:

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

Ne yapabilirim? Google, bunun yanlış bir şekilde .csv olarak kaydedilmiş bir Excel dosyası olabileceğini öne sürüyor. Python'da bu sorunu aşmanın bir yolu var mı?

== GÜNCELLEME ==

@ JohnMachin'in aşağıdaki yorumunu takiben, bu satırları betiğime eklemeyi denedim:

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

Ve aldığım çıktı bu:

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

Yani dosya gerçekten NUL baytları içeriyor.


Ne yok od -cgibi ilk satırı görünüyor ki?
Ignacio Vazquez-Abrams

hangi sorguyu çalıştırmalıyım, cat my.csv gibi bir şey | od -c | Daha ? bununla şunu elde ederim: 0000000 D epartment F amil
AP257

CSV nasıl oluşturulur? Excel'den, bir lehçeyi deneyebilirsiniz. Aksi takdirde şunu söyleyin: stackoverflow.com/questions/2753022/…
dr jimbob

Teşekkürler. Benim CSV'm değil ve maalesef onu değiştirecek gücüm yok. Sanırım Excel olarak oluşturuldu ve CSV (boo) olarak kaydedildi. Bir lehçe kulağa iyi bir fikir gibi geliyor - bunu deneyeceğim!
AP257

Aslında CSV olarak kaydedilmişse, çalışmalıdır. Bazen bulduğum bir şey, CSV olarak maskelenen TSV (sekmeyle ayrılmış) dosyalarıdır, bu nedenle bir '\ t' ayırıcısı ayarlamayı deneyebilirsiniz. Bir Excel dosyası olarak kaydedilmişse ve uzantı CSV olarak değiştirilmişse, hiçbir lehçe çalışmayacaktır. Bu durumda tek seçeneğinizin, kopyaları uygun CSV olarak kaydetmek için Excel'i kullanmak olacağını düşünüyorum.
Thomas K

Yanıtlar:


104

@ S.Lott'un dediği gibi, dosyalarınızı 'rU' modunda değil, 'rb' modunda açmalısınız. Ancak bu, mevcut sorununuza neden OLMAYABİLİR. Bildiğim kadarıyla, 'rU' modunu kullanmak \r, verilere gömülü ise sizi mahveder , ancak başka dramalara neden olmaz. Ayrıca birkaç dosyanız (tümü 'rU' ?? ile açılmış) olduğunu, ancak yalnızca birinin soruna neden olduğunu not ediyorum.

Eğer csv modülü dosyanızda "NULL" (saçma mesaj, "NUL" olmalıdır) baytınız olduğunu söylüyorsa, dosyanızda ne olduğuna bakmanız gerekir. 'Rb' kullanmak sorunu çözse bile bunu yapmanızı öneririm.

repr()sizin hata ayıklama arkadaşınız (veya olmak istiyor). Platformdan bağımsız bir şekilde neye sahip olduğunuzu net bir şekilde gösterecektir (bu, ne odolduğunu veya ne yaptığını bilmeyen yardımcılar için yararlıdır ). Bunu yap:

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

ve sonucu dikkatlice kopyalayıp / yapıştırarak (yeniden yazmayın) sorunuzun bir düzenlemesine (yoruma değil).

Ayrıca, dosya gerçekten tehlikeli ise, örneğin dosyanın başlangıcından itibaren makul bir mesafede \ r veya \ n yok ise, tarafından bildirilen satır numarasının reader.line_num(yararsız bir şekilde) olacağını unutmayın 1. \x00Bunu yaparak (varsa) ilkinin nerede olduğunu bulun

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

ve repr veya od ile en azından bu kadar baytı boşalttığınızdan emin olun.

Sana ne data.count('\x00')anlatıyor Çok fazla varsa, şöyle bir şey yapmak isteyebilirsiniz

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

NUL baytlarını bağlam içinde görebilmeniz için.

Eğer görebiliyorsanız \x00(veya çıktıda \0sizin de od -cçıktı), o zaman kesinlikle dosyasında boş karakter (ler) varsa ve böyle bir şey yapmak gerekir:

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

Bu arada, dosyaya (son birkaç satır dahil) bir metin düzenleyiciyle baktınız mı? Diğer dosyalar gibi ("NULL bayt" istisnası olmayan) makul bir CSV dosyası gibi mi görünüyor?


Bu detaylı yardım için çok teşekkür ederim. Dosyada çok sayıda \ x00 karakter var (soruya göre düzenlemeye bakın) - bu garip, çünkü bir metin düzenleyicide tamamen makul bir CSV dosyası gibi görünüyor.
AP257

1
@ AP257: '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1OLE2 Bileşik Belge dosyasını belirten "imzadır" - örneğin bir Excel 97-2003 .XLS dosyası . "Bir metin düzenleyicide tamamen makul bir CSV dosyası gibi görünüyor" ifadesini tamamen inanılmaz buluyorum . Farklı bir dosyaya, geçerli bir CSV dosyasına, başka bir klasöre veya başka bir makineye veya başka bir zamanda bakıyor olmalısınız. odÇıktınızın bir XLS dosyasından olmadığını unutmayın .
John Machin

8
@ AP257: Bu cevabı kabul etmemenizin özel bir nedeni var mı?
John Machin

Çalışır, ancak CSV'yi filtreleyen ve csv.readerdoğrudan aktarılabilen dosya benzeri bir nesneyle anında mümkün ve güzel olmalıdır .
gerrit

1
Gerekmiyor fo.write(data.replace('\x00', ''))olmak fo.write(data.replace(b'\x00', b''))? Python 3.6 burada ...
Boern

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

Bu benim için çalışıyor.


Benim durumum için çözüldü, null '\ 0' değerleriydi. Teşekkürler.
Joab Mendes

19

UTF-16 olarak okumak da benim sorunumdu.

İşte sonuçta işe yarayan kodum:

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

Konum, csv dosyanızın dizinidir.


13

Ben de bu problemle karşılaştım. Python csvmodülünü kullanarak, MS Excel'de oluşturulan ve aldığınız NULL bytehatayla karşılaşan bir XLS dosyasını okumaya çalışıyordum . Etrafıma baktım ve MS Excel elektronik tablo dosyalarından veri okumak ve biçimlendirmek için xlrd Python modülünü buldum . xlrdModül ile hem dosyayı düzgün okuyabiliyorum hem de dosyanın birçok farklı kısmına daha önce yapamadığım şekilde erişebiliyorum.

Sana yardımcı olabileceğini düşündüm.


7
Bu modülü gösterdiğin için teşekkürler. Yeterince ilginç bir şekilde, indirmeye gittim ve yazarın, bu sorunun en iyi yorumu olan @John_Machin'den başkası olmadığını fark ettim.
Evan

11

Kaynak dosyanın kodlamasını UTF-16'dan UTF-8'e dönüştürmek sorunumu çözüyor.

Python'da bir dosya utf-8'e nasıl dönüştürülür?

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)

8

Yokmuş gibi davranmak istiyorsanız, boş değerleri filtrelemek için bir üreteci satır içi yapabilirsiniz. Elbette bu, boş baytların kodlamanın gerçekten bir parçası olmadığını ve gerçekten bir tür hatalı yapaylık veya hata olduğunu varsaymaktır.

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

Bunu neden yapıyorsun?

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

Dokümanlar, bunu yapmanız gerektiği konusunda oldukça açık:

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

Mod okumak için "rb" olmalıdır.

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

Eğer csvfile bir dosya nesnesiyse, fark yaratan platformlarda 'b' bayrağıyla açılmalıdır.


@ AP257: "Yardımcı olmuyor"? Ne demek? Herhangi bir özel hata mesajı var mı?
S. Lot

1
@ S.Lott: Öncekiyle aynı yanıtı aldığı anlamına gelir. Gerçek şu ki, bir bukalemun ya da şekil değiştirici dosyasıyla uğraşıyor ... dosyayı döktüğünde ya odda bir metin düzenleyicide ona baktığında, tamamen normal bir CSV dosyası gibi görünüyor. Bununla birlikte, Python repr () ile ilk birkaç baytı döktüğünde, bir Excel .XLS dosyası gibi yapar (bu, bir CSV uzantısına sahip olacak şekilde yeniden adlandırılmıştır).
John Machin

@John Machin: "Bir Excel .XLS dosyası (CSV uzantısına sahip olacak şekilde yeniden adlandırılmıştır" Hiçbir şekilde işlenemeyeceği anlamına gelir.
S.Lott

1
@ S.Lott: Bu içerikle csv modülünün onu işleyemeyeceği anlaşılıyor; ancak xlrd modülü bunu işleyebilir. Mantıklı bir şekilde, her iki modül de giriş dosyasının adından bir şey çıkarmaz, eğer gerçekten giriş bir ada sahip bir dosyaysa.
John Machin

1
@John Machin: "Her iki modül de girdi dosyasının adından bir şey çıkarmaz". Doğru. Benim uygulama çerçevem ​​bu gerçeğe bağlı. İnsanlar hata yaptığı için ("yalan") dosya adının bir anlam ifade edeceğine güvenmiyoruz. Bu yüzden, bir tıklamaya kadar bir dizi alternatifi kontrol etmeliyiz.
S. Lot


2

Csv okuyucu yerine string için dosya oku ve bölme işlevini kullanıyorum:

lines = open(input_file,'rb') 

for line_all in lines:

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

1

Aynı hatayı aldım. Dosyayı UTF-8 olarak kaydetti ve çalıştı.


1
Aynı hata mesajını almış olabilirsiniz, ancak nedeni farklı olabilirdi - muhtemelen orijinal olarak UTF-16 olarak kaydettiniz (Not Defteri "Unicode" olarak adlandırılır).
John Machin

1

Bu, OpenOffice Calc ile bir CSV dosyası oluşturduğumda başıma geldi. CSV dosyasını metin düzenleyicimde oluşturduğumda, daha sonra Calc ile düzenlesem bile olmadı.

Metin düzenleyicimde Calc ile oluşturduğum dosyadaki verileri düzenleyici tarafından oluşturulan yeni bir dosyaya kopyalayıp yapıştırarak sorunumu çözdüm.


1

Boş başlıklara NULL bayt ekleyen bir web hizmetinden üretilen bir CSV'yi açarken aynı sorunu yaşadım. Dosyayı temizlemek için aşağıdakileri yaptım:

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

Sorumluluk reddi: Bunun orijinal verilerinizin üzerine yazdığını unutmayın. Yedek bir kopyasına sahip olduğunuzdan emin olun. Uyarıldın!


0

Tüm bu 'rU' dosya modundan nefret edenler için: Mac'te bir Windows makinesinden 'rb' dosya moduyla bir CSV dosyası açmayı denedim ve bu hatayı csv modülünden aldım:

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

Dosyayı 'rU' modunda açmak iyi çalışıyor. Evrensel yeni satır modunu seviyorum - beni çok fazla güçlükten kurtarıyor.


0

Bununla karşılaştım, csvreader'a teslim etmeden önce yanıt gövdesini açmak için doğru bir ara katman yazılımı olmadan sıkıştırılmış bir csv dosyasını indirirken ve hurda kullanırken karşılaştım. Dolayısıyla dosya gerçekten bir csv dosyası değildi ve line contains NULL bytehatayı buna göre attı .


0

Gzip.open kullanmayı denediniz mi?

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

Sıkıştırılmış ancak "csv.gz" yerine ".csv" uzantılı bir dosyayı açmaya çalışıyordum. Bu hata gzip.open'i kullanana kadar gösterilmeye devam etti


-1

Bir durum şudur - CSV dosyası boş satırlar içeriyorsa, bu hata görünebilir. Yazmaya veya okumaya devam etmeden önce satırı kontrol etmek gereklidir.

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

Bu çeki koda ekleyerek sorunumu çözdüm.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.