"Рядок містить байт NULL" у програмі зчитування CSV (Python)


84

Я намагаюся написати програму, яка переглядає файл .CSV (input.csv) і переписує лише ті рядки, які починаються з певного елемента (corrected.csv), як зазначено у текстовому файлі (output.txt).

Ось як зараз виглядає моя програма:

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)

На жаль, я постійно отримую цю помилку і не маю уявлення, про що йдеться.

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

Всім людям тут честь навіть довести мене до цього моменту.


Тільки здогадуйтесь, але схоже, що файл input.csv містить порожній рядок (мебе в кінці?). Спробуйте шукати у файлі csvParser.py цей текст винятку.
Sam Axe

Я насправді щойно переглянув файл input.csv і позбувся будь-якого порожнього місця ... все ще не везе (та сама помилка).
James Roseman

Щоб визначити номер рядка, пропоную ввести змінну лічильника та збільшити її в межах for row in readerциклу.
codeape

Я не впевнений, як я повинен це робити, коли сама програма не буде виконуватися. Я спробував додати лічильник, і нічого іншого не з’явилося, лише та сама помилка зворотного відстеження.
Джеймс Роузман

4
У вас є файл NULL у вашому .csv? open('input.csv').read().index('\0')дасть вам компенсацію першого, якщо ви це зробите.
повторити

Відповіді:


66

Я вирішив подібну проблему за допомогою більш простого рішення:

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

Ключ використовував модуль кодеків для відкриття файлу з кодуванням UTF-16, є набагато більше кодування, перевірте документацію .


4
У мене була така сама проблема з файлом CSV, створеним з LibreOffice, який спочатку відкривався з файлу .xls Excel. З якоїсь причини LibreOffice зберегла файл CSV як UTF-16. Ви можете зрозуміти, подивившись перші 2 байти файлу, якщо це FF FE, то це хороший показник того, що це UTF-16
Том Далтон,

4
Зверніть увагу, що якщо ваш файл містить дані UTF-16, які перебувають за межами діапазону ASCII, csv.reader() вони не зможуть обробляти їх, і UnicodeEncodeErrorзамість цього ви отримаєте s.
Мартін Пітерс

6
Це просто спричинило іншу помилку,UnicodeError: UTF-16 stream does not start with BOM
Церін

У моєму випадку це було 'utf-16le'.
Павел Щур

69

Я здогадуюсь, що у вас є байт NUL у input.csv. Ви можете перевірити це за допомогою

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

Якщо ти зробиш,

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

може вас обігнати. Або це може означати, що у вас є файл utf16 або щось “цікаве” у файлі .csv.


5
+1 щодо пошуку NULL-байтів у файлі ... на жаль, тепер мій файл 'corrected.csv' тепер читається японською мовою ...
James Roseman

Здається, ваш .csv не в ascii. Я думаю, що подальша допомога вимагатиме трохи більше інформації про фактичний вміст вашого .csv. Ви пробували відкрити його в текстовому редакторі, наприклад vim або блокноті? Або працює, file input.csvщоб визначити тип файлу?
повторний

Я відкрив його в Блокноті, і це виглядає нормально. Як повинен виглядати CSV? Він читається так само, як і в Google Analytics, але з величезними вкладками між даними.
Джеймс Роузман

Блін ... чи є спосіб замінити вкладки комами і змусити це працювати з програмою Python?
James Roseman

1
Якщо CSV обмежений вкладці необхідно вказати так: reader = csv.reader(mycsv, delimiter='\t'). Я уявляю, що програма читання CSV з’їдає весь ваш файл, шукаючи коми і потрапляючи аж до EOF. Але у вас точно є проблема з кодуванням. Вам потрібно вказати кодування під час відкриття файлу.
Steven Rumbalski

11

Якщо ви хочете замінити нулі чимось, ви можете зробити це:

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

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

2
Заміна null на пробіл не буде вдалим вибором. Мені вдалося замінити порожній рядок
Марсело Ассіс,

У мене питання про те, як ви використали урожай. Враховуючи те, що це в циклі, чи означає це, що він все одно буде читати файл, рядок за рядком, чи він завантажує його в пам'ять відразу?
mnsr

10

Ви можете просто вбудувати генератор, щоб відфільтрувати нульові значення, якщо ви хочете зробити вигляд, що вони не існують. Звичайно, це припускає, що нульові байти насправді не є частиною кодування, а насправді є якимось помилковим артефактом чи помилкою.

Дивіться (line.replace('\0','') for line in f)нижче, також ви захочете відкрити цей файл за допомогою режиму 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)

Дякую! Це спрацювало для файлів результатів виборів у Північній Кореї, які справді (!) Використовують нульовий байт замість байта "0" в одному стовпці. Дивіться dl.ncsbe.gov/ENRS/resultsPCT20161108.zip
nealmcb

7

Це підкаже, в чому саме проблема.

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

Можливо, це від daniweb було б корисним:

Я отримую цю помилку під час читання з файлу csv: "Помилка виконання! Рядок містить NULL байт". Будь-яке уявлення про першопричину цієї помилки?

...

Гаразд, я зрозумів і думав, що опублікую рішення. Просто все-таки викликав у мене горе ... Використаний файл було збережено у форматі .xls замість .csv Не вдалося зрозуміти це, оскільки саме ім'я файлу мало розширення .csv, поки тип ще був .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

В порядку. Тоді це задихання на першій лінії. Запустіть це та опублікуйте print(open('input.csv', 'r').readlines()[0])
побачене

Щось забавне ... але це працює. ÿþ/<Це все, що можна було б вставити (в основному це блоки та цифри)
Джеймс Роузман,

1
Можливо, ваш CSV насправді не є CSV. Дивіться другу половину моєї відповіді.
Steven Rumbalski

О, стріляйте, це могло бути цілком, як я можу це виправити? Я також врятував це прямо з Google Analytics ...
Джеймс Роузман,

2

Хитрий спосіб:

Якщо ви розробляєте в рамках Lunux, ви можете використовувати всю силу 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)    

Найефективніше рішення для величезних файлів.

Перевірено на наявність Python3, Kubuntu


1

Нещодавно я вирішив цю проблему, і в моєму випадку це був стислий файл, який я намагався прочитати. Спочатку перевірте формат файлу. Потім переконайтеся, що вміст стосується розширення.


1

Перетворення мого середовища Linux на чисте повне середовище UTF-8 зробило для мене фокус. Спробуйте наступне у своєму командному рядку:

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

для мене також перехід на UTF-8 вирішив проблему. У Windows я використовував Notepad ++ для зміни формату з UTF16 на UTF8. Потім я відкрив файл за допомогою програми libreoffice calc та очистив зайві рядки тощо.
Юваль Гарпаз,

1

Це давно врегульовано, але я натрапив на цю відповідь, оскільки під час читання CSV-файлу під час читання CSV-файлу у мене виникли непередбачені помилки, які оброблялись як навчальні дані в Keras та TensorFlow.

У моєму випадку питання було набагато простішим, і про це варто пам’ятати. Дані, що надходять у CSV, не були послідовними, що призвело до того, що деякі стовпці повністю відсутні, що, здається, в кінцевому підсумку викидає і цю помилку.

Урок: Якщо ви бачите цю помилку, переконайтеся, що ваші дані виглядають так, як ви думаєте!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.