“Dòng chứa byte NULL” trong trình đọc CSV (Python)


84

Tôi đang cố gắng viết một chương trình xem tệp .CSV (input.csv) và chỉ viết lại các hàng bắt đầu bằng một phần tử nhất định (fixed.csv), như được liệt kê trong tệp văn bản (output.txt).

Đây là những gì chương trình của tôi trông giống như ngay bây giờ:

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)

Thật không may, tôi vẫn gặp lỗi này và tôi không biết nó là gì.

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

Tín dụng cho tất cả những người ở đây để giúp tôi đến thời điểm này.


Chỉ là phỏng đoán nhưng có vẻ như tệp input.csv của bạn chứa một dòng trống (mebe ở ​​cuối?). Hãy thử tìm kiếm trong tệp csvParser.py cho văn bản ngoại lệ đó.
Sam Axe

Tôi thực sự chỉ xem qua tệp input.csv và loại bỏ bất kỳ và tất cả không gian trống ... vẫn không may mắn (cùng một lỗi).
James Roseman

Để xác định chính xác số dòng, tôi khuyên bạn nên giới thiệu một biến bộ đếm và tăng nó trong for row in readervòng lặp.
codeape

Tôi không chắc mình phải làm như thế nào khi bản thân chương trình sẽ không thực thi. Tôi đã thử thêm bộ đếm và không có gì khác biệt xuất hiện, chỉ là cùng một lỗi truy xuất.
James Roseman

4
Bạn có byte NULL trong .csv của mình không? open('input.csv').read().index('\0')sẽ cung cấp cho bạn phần bù của cái đầu tiên nếu bạn làm như vậy.
khôi phục lại

Câu trả lời:


66

Tôi đã giải quyết một vấn đề tương tự bằng một giải pháp dễ dàng hơn:

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

Chìa khóa là sử dụng mô-đun codec để mở tệp với mã hóa UTF-16, có rất nhiều mã hóa khác, hãy kiểm tra tài liệu .


4
Tôi đã gặp sự cố tương tự với tệp CSV được tạo từ LibreOffice, tệp này ban đầu được mở từ tệp .xls của Excel. Vì một số lý do, LibreOffice đã lưu tệp CSV dưới dạng UTF-16. Bạn có thể nói bằng cách nhìn vào 2 byte đầu tiên của tập tin, nếu nó FF FE thì đó là một dấu hiệu tốt rằng nó UTF-16
Tom Dalton

4
Lưu ý rằng nếu tệp của bạn chứa dữ liệu UTF-16 nằm ngoài phạm vi ASCII csv.reader() sẽ không thể xử lý được UnicodeEncodeErrorvà thay vào đó bạn sẽ nhận được s.
Martijn Pieters

6
Điều này chỉ gây ra một lỗi khác được phát sinh,UnicodeError: UTF-16 stream does not start with BOM
Cerin

Trong trường hợp của tôi là như vậy 'utf-16le'.
Paweł Szczur,

69

Tôi đoán bạn có một byte NUL trong input.csv. Bạn có thể kiểm tra điều đó với

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

nếu bạn làm,

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

có thể giúp bạn vượt qua điều đó. Hoặc nó có thể cho biết bạn có utf16 hoặc thứ gì đó 'thú vị' trong tệp .csv.


5
1 vào việc tìm kiếm NULL byte trong file ... unforetunately tại tập tin 'corrected.csv' của tôi bây giờ đọc bằng tiếng Nhật ...
James Roseman

Có vẻ như .csv của bạn không có trong ascii. Tôi nghĩ rằng trợ giúp thêm sẽ yêu cầu thêm một chút thông tin về nội dung thực tế của .csv của bạn. Bạn đã thử mở nó trong một trình soạn thảo văn bản như vim hoặc notepad chưa? Hoặc chạy file input.csvđể xác định loại tệp?
retracement

Tôi đã mở nó bằng Notepad và nó có vẻ ổn. Csv phải như thế nào? Nó đọc giống như trên Google Analytics, nhưng với các tab lớn giữa dữ liệu.
James Roseman

Chết tiệt ... có cách nào để thay thế các tab bằng dấu phẩy và nó có hoạt động với chương trình Python không?
James Roseman

1
Nếu csv của bạn được phân định tab bạn cần phải xác định như vậy: reader = csv.reader(mycsv, delimiter='\t'). Tôi hình dung rằng trình đọc csv đang đọc toàn bộ tệp của bạn để tìm dấu phẩy và tìm mọi cách đến EOF. Nhưng bạn chắc chắn có vấn đề về mã hóa. Bạn cần chỉ định mã hóa khi mở tệp.
Steven Rumbalski

11

Nếu bạn muốn thay thế null bằng một cái gì đó, bạn có thể làm như sau:

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

r = csv.reader(fix_nulls(open(...)))

2
Thay thế null bằng một khoảng trắng sẽ không phải là một lựa chọn tốt. Đã làm việc để tôi thay thế bằng một chuỗi trống
Marcelo Assis

Tôi có một câu hỏi về cách bạn đã sử dụng lợi nhuận. Cho rằng đây là một vòng lặp, điều đó có nghĩa là nó sẽ vẫn đọc từng dòng của tệp hay sẽ tải nó vào bộ nhớ cùng một lúc?
mnsr

10

Bạn chỉ có thể nội dòng một trình tạo để lọc ra các giá trị null nếu bạn muốn giả sử chúng không tồn tại. Tất nhiên, điều này là giả định các byte rỗng không thực sự là một phần của mã hóa và thực sự là một số loại lỗi hoặc lỗi tạo tác sai lầm.

Xem phần (line.replace('\0','') for line in f)bên dưới, bạn cũng có thể muốn mở tệp đó bằng chế độ 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)

Cảm ơn! Điều này hoạt động đối với các tệp kết quả bầu cử NC, tệp này thực sự (!) Sử dụng byte rỗng thay cho byte "0" trong một cột. Xem dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb

7

Điều này sẽ cho bạn biết dòng nào là vấn đề.

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

Có lẽ điều này từ daniweb sẽ hữu ích:

Tôi gặp lỗi này khi đọc từ tệp csv: "Lỗi thời gian chạy! Dòng chứa byte NULL". Bất kỳ ý tưởng về nguyên nhân gốc rễ của lỗi này?

...

Ok, tôi đã hiểu và nghĩ rằng tôi sẽ đăng giải pháp. Chỉ đơn giản là khiến tôi đau buồn ... Tệp đã sử dụng được lưu ở định dạng .xls thay vì .csv Không hiểu được điều này vì bản thân tên tệp có phần mở rộng .csv trong khi loại vẫn là .xls


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

Đồng ý. Sau đó, nó nghẹt thở ngay từ dòng đầu tiên. Khởi này và gửi những gì bạn thấy:print(open('input.csv', 'r').readlines()[0])
Steven Rumbalski

Một cái gì đó sôi nổi ... nhưng nó đang chạy. ÿþ/<Đó là tất cả nó sẽ dán (nó chủ yếu là khối và số)
James Roseman

1
Có lẽ csv của bạn không thực sự là csv. Xem nửa sau câu trả lời của tôi.
Steven Rumbalski

Ồ, hoàn toàn có thể là nó, tôi có thể sửa lỗi này bằng cách nào? Tôi lưu nó trực tiếp từ Google Analytics quá ...
James Roseman

2

Một cách khó:

Nếu bạn phát triển dưới Lunux, bạn có thể sử dụng tất cả sức mạnh của 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)    

Giải pháp hiệu quả nhất cho các tệp lớn.

Đã kiểm tra Python3, Kubuntu


1

Gần đây tôi đã khắc phục sự cố này và trong trường hợp của tôi, đó là một tệp đã được nén mà tôi đang cố đọc. Kiểm tra định dạng tệp trước. Sau đó, kiểm tra xem nội dung có phải là những gì tiện ích mở rộng đề cập đến không.


1

Biến môi trường linux của tôi thành một môi trường UTF-8 hoàn chỉnh sạch sẽ đã tạo nên một mẹo nhỏ cho tôi. Hãy thử những điều sau trong dòng lệnh của bạn:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

đối với tôi, việc thay đổi thành UTF-8 cũng giải quyết được vấn đề. Trên windows, tôi đã sử dụng Notepad ++ để thay đổi định dạng từ UTF16 thành UTF8. Sau đó tôi mở tập tin với LibreOffice Calc, và xóa thêm dòng, vv
Yuval Harpaz

1

Điều này đã được giải quyết từ lâu, nhưng tôi gặp phải câu trả lời này vì tôi gặp phải lỗi không mong muốn khi đọc CSV để xử lý dưới dạng dữ liệu đào tạo trong Keras và TensorFlow.

Trong trường hợp của tôi, vấn đề đơn giản hơn nhiều và đáng được lưu ý. Dữ liệu được tạo vào CSV không nhất quán, dẫn đến một số cột bị thiếu hoàn toàn, điều này dường như cũng dẫn đến lỗi này.

Bài học: Nếu bạn gặp lỗi này, hãy xác minh rằng dữ liệu của bạn trông giống như bạn nghĩ!


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.