UnicodeDecodeError: кодек «utf8» не может декодировать байт 0xa5 в позиции 0: недопустимый начальный байт


189

Я использую Python-2.6 CGIсценарии, но обнаружил эту ошибку в журнале сервера при выполнении json.dumps(),

Traceback (most recent call last):
  File "/etc/mongodb/server/cgi-bin/getstats.py", line 135, in <module>
    print json.dumps(​​__get​data())
  File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa5 in position 0: invalid start byte

Здесь

​__get​data()функция возвращает dictionary {}.

Перед тем, как опубликовать этот вопрос, я передал этот вопрос по поводу SO.


ОБНОВЛЕНИЕ

Следующая строка повреждает кодер JSON,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) // this is the culprit

Я получил временное решение для этого

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

Но я не уверен, что это правильный способ сделать это.


1
Похоже, у вас есть некоторые строковые данные в словаре, которые нельзя кодировать / декодировать. Что в dict?
— Мгилсон

@mgilson yup master Я понял проблему, но не знаю, как с ней справиться .. dictимеетlist, dict, python timestamp value
— Deepak Ingole

1
@ Пилот - Не совсем. Настоящая проблема похоронена где-то в __getdata. Я не знаю, почему вы получаете не декодируемый персонаж. Вы можете попытаться придумать исправления, чтобы заставить его работать, но они в основном просто требуют дополнительных проблем позже. Я бы попробовал напечатать диктовку, чтобы увидеть, где находится не-ascii символ. Затем выясните, как было вычислено / установлено это поле, и работайте в обратном направлении.
— Мгилсон


1
У меня была та же самая ошибка при попытке прочитать файл .csv, в котором были некоторые символы, отличные от ascii. Удаление этих символов (как предложено ниже) решило проблему.
— Дмитрий Р. Старсон

Ответы:


87

Ошибка в том, что в словаре есть какой-то не-ascii символ, и его нельзя кодировать / декодировать. Один простой способ избежать этой ошибки - закодировать такие строки с помощью encode()функции следующим образом (если aэто строка с не-ascii символом):

a.encode('utf-8').strip()

2
Так как UTF-8 обратно совместим с oldschool 7-bit ASCII, вы должны просто все кодировать. Для символов в 7-битном диапазоне ASCII эта кодировка будет отображением идентичности.
— Тадеуш А. Кадлубовски

29
Это не совсем понятно. При импорте файла CSV, как вы используете этот код?
— Дейв

Такая же проблема возникает для меня при выполнении запроса sqlalchemy, как бы я закодировал запрос (не имеет .encode, так как это не строка)?
— c8999c 3f964f64

133

Я переключил это просто, определив другой пакет кодеков в read_csv()команде:

encoding = 'unicode_escape'

Например:

import pandas as pd
data = pd.read_csv(filename, encoding= 'unicode_escape')

1
Только если вы используетеpandas
— Валерий

1
извините, это не сработало, у меня снова была та же ошибка. но когда я использовал ('filename.csv', engine = 'python'). Это сработало.
— basavaraj_S

117

Попробуйте приведенный ниже фрагмент кода:

with open(path, 'rb') as f:
  text = f.read()

7
Я имел rвместо rb. спасибо за напоминание добавить b!
— Пол

1
По умолчанию openфункция имеет режим «только для чтения». rbрасшифровывается как бинарный режим чтения.
— Шива

39

В вашей строке asciiзакодирован не символ.

Невозможность декодирования utf-8может произойти, если вам нужно использовать другие кодировки в вашем коде. Например:

>>> 'my weird character \x96'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x96 in position 19: invalid start byte

В этом случае кодировка такова windows-1252:

>>> 'my weird character \x96'.decode('windows-1252')
u'my weird character \u2013'

Теперь, когда у вас есть Unicode, вы можете безопасно кодировать в utf-8.


1
Я создал простую страницу, которая может помочь установить кодировку некоторых неожиданных «тайных байтов»; tripleee.github.io/8bit
— tripleee


16

Установите кодировщик по умолчанию в верхней части вашего кода

import sys
reload(sys)
sys.setdefaultencoding("ISO-8859-1")

Я думаю, что Python3 не имеет setdefaultencoding в модуле sys!
— Анвар Хоссейн

14

По состоянию на 2018-05 это выполняется напрямую decode, по крайней мере, для Python 3 .

Я использую ниже фрагмент кода для invalid start byteи invalid continuation byteошибок типа. Добавление errors='ignore'исправило это для меня.

with open(out_file, 'rb') as f:
    for line in f:
        print(line.decode(errors='ignore'))

1
Конечно, это молча отбрасывает информацию. Гораздо лучше исправить это, чтобы выяснить, что должно быть там, и исправить первоначальную проблему.
— tripleee

14

Вдохновленный @aaronpenne и @Soumyaansh

f = open("file.txt", "rb")
text = f.read().decode(errors='replace')

Я получил "AttributeError: у объекта 'str' нет атрибута 'decode'". Не уверен, что пошло не так?
— Виктор Вонг

Вы включили б в "рб"? B предназначен для открытия файла в байтовом формате. Если вы просто используете r, это строка, и не включать декодирование.
— Пуннеруд

14

Это решение сработало для меня:

import pandas as pd
data = pd.read_csv("training.csv", encoding = 'unicode_escape')

11

Простое решение:

import pandas as pd
df = pd.read_csv('file_name.csv', engine='python')

3
Спасибо, что помогли!
— Рубен

Рад помочь @Ruben
— Gil Baggio

2
Спасибо, это помогло мне. Я работал над пандами.
— Еще

Рад помочь @basavaraj_S
— Гил Баджо

1
Единственное решение, которое работает для меня из всех представленных здесь.
— Lunesco

7

Следующая строка повреждает кодер JSON,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) // this is the culprit

Я получил временное решение для этого

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

Отмечать это так же правильно, как временное исправление (не уверен).


5

Если вышеуказанные методы не работают для вас, вы можете захотеть изменить кодировку самого файла CSV.

Используя Excel:

  1. Открыть CSV-файл с помощью Excel
  2. Перейдите к пункту «Файл меню» и нажмите «Сохранить как»
  3. Нажмите «Обзор», чтобы выбрать место для сохранения файла.
  4. Введите предполагаемое имя файла
  5. Выберите параметр CSV (с разделителями-запятыми) (* .csv)
  6. Нажмите «Инструменты» в раскрывающемся списке и нажмите «Веб-параметры»
  7. На вкладке «Кодировка» выберите опцию Unicode (UTF-8) в раскрывающемся списке «Сохранить этот документ».
  8. Сохранить файл

Используя Блокнот:

  1. Открыть CSV-файл с помощью блокнота
  2. Перейдите к «Файл»> «Сохранить как» вариант
  3. Далее выберите место для файла
  4. Выберите опцию Сохранить как тип как Все файлы ( . )
  5. Укажите имя файла с расширением .csv
  6. В раскрывающемся списке «Кодировка» выберите опцию UTF-8.
  7. Нажмите Сохранить, чтобы сохранить файл

Сделав это, вы сможете импортировать CSV-файлы, не встречая UnicodeCodeError.


2

После попытки всех вышеупомянутых обходных путей, если это все еще выдает ту же ошибку, вы можете попробовать экспортировать файл как CSV (второй раз, если у вас уже есть). Особенно, если вы используете Scikit Learn, лучше всего импортировать набор данных в виде файла CSV.

Я провел часы вместе, тогда как решение было таким простым. Экспортируйте файл в формате CSV в каталог, где установлены Anaconda или ваши инструменты классификатора, и попробуйте.


2

Вы можете использовать любую стандартную кодировку вашего конкретного использования и ввода.

utf-8 по умолчанию.

iso8859-1 также популярен в Западной Европе.

например: bytes_obj.decode('iso8859-1')

смотри: документы


1
Слепое предположение, что кодирование может вызвать больше ошибок. Выбор iso8859-1 или cp1251 и т. Д. Без фактического знания, какую кодировку использует файл, устранит этот симптом, но приведет к появлению мусора, если вы угадали. Если это всего несколько байтов, могут пройти годы, прежде чем вы заметите и исправите настоящую ошибку.
— Трипли

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.