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(​​__getdata())
  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')
MSalty
источник
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
34

На чтение csvя добавил метод кодирования:

import pandas as pd
dataset = pd.read_csv('sample_data.csv', header= 0,
                        encoding= 'unicode_escape')
Кришна прасад.м
источник
16

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

import sys
reload(sys)
sys.setdefaultencoding("ISO-8859-1")
HimalayanCoder
источник
Я думаю, что 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'))
aaronpenne
источник
1
Конечно, это молча отбрасывает информацию. Гораздо лучше исправить это, чтобы выяснить, что должно быть там, и исправить первоначальную проблему.
tripleee
14

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

f = open("file.txt", "rb")
text = f.read().decode(errors='replace')
Punnerud
источник
Я получил "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 или ваши инструменты классификатора, и попробуйте.

Sushmita
источник
2

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

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

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

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

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

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