Python - кодек ascii не может декодировать байт

Я действительно смущен. Я пытался кодировать, но ошибка сказала can't decode....

>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

Я знаю, как избежать ошибки с префиксом "u" в строке. Мне просто интересно, почему ошибка "не может декодироваться" при вызове encode. Что делает Python под капотом?

Ответ 1

"你好".encode('utf-8')

encode преобразует объект unicode в объект string. Но здесь вы вызывали его на объект string (потому что у вас нет u). Таким образом, python должен сначала преобразовать объект string в объект unicode. Таким образом, это эквивалентно

"你好".decode().encode('utf-8')

Но декодирование не выполняется, потому что строка недействительна ascii. Вот почему вы получаете жалобу о невозможности декодирования.

Ответ 2

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

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

Другой способ - декодировать от байтов до unicode.
В этом направлении вам нужно знать, что кодировка.

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

Эта точка не может быть подчеркнута достаточно. Если вы хотите избежать воспроизведения unicode "whack-a-mole", важно понять, что происходит на уровне данных. Здесь это объясняется по-другому:

  • Объект unicode уже декодирован, вы никогда не хотите называть его decode.
  • Объект bytestring уже закодирован, вы никогда не хотите называть его encode.

Теперь, увидев .encode в байтовой строке, Python 2 сначала пытается неявно преобразовать его в текст (объект unicode). Аналогично, при просмотре .decode в строке unicode Python 2 неявно пытается преобразовать его в байты (объект str).

Эти неявные преобразования - вот почему вы можете получить unicode decode Error, когда вы вызываете encode. Это потому, что кодировка обычно принимает параметр типа unicode; при приеме параметра str существует неявное декодирование в объект типа unicode перед повторным кодированием его с другим кодированием. Это преобразование выбирает дешифратор "ascii" по умолчанию что дает вам ошибку декодирования внутри кодера.

Фактически, в Python 3 методы str.decode и bytes.encode даже не существуют. Их устранение было [противоречивой] попыткой избежать этой общей путаницы.

... или что-то вроде кодирования sys.getdefaultencoding(); обычно это "ascii"

Ответ 3

Вы можете попробовать это

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

или

Вы также можете попробовать

Добавьте следующую строку вверху вашего .py файла.

# -*- coding: utf-8 -*- 

Ответ 4

Если вы используете Python < 3, вам нужно сообщить интерпретатору, что ваш строковый литерал является Unicode, префикс его u:

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'

Дальнейшее чтение: Unicode HOWTO.

Ответ 5

Вы используете u"你好".encode('utf8') для кодирования строки в Юникоде. Но если вы хотите представить "你好", вы должны его декодировать. Также как:

"你好".decode("utf8")

Вы получите то, что хотите. Возможно, вам стоит больше узнать о кодировании и декодировании.

Ответ 6

Если вы имеете дело с Unicode, иногда вместо encode('utf-8') вы также можете игнорировать специальные символы, например.

"你好".encode('ascii','ignore')

или something.decode('unicode_escape').encode('ascii','ignore'), как предлагается здесь.

Не особенно полезен в этом примере, но может работать лучше в других сценариях, когда невозможно преобразовать некоторые специальные символы.

В качестве альтернативы вы можете рассмотреть замену определенного символа с помощью replace().