Кодек 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 под капотом?

7 ответов


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

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

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

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


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

>>> 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 сначала пытается неявно преобразовать ее в текст (a


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

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

или

вы можете попробовать следующие

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

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

Если вы используете Python строковый литерал является 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.


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

"你好".decode("utf8")

вы получите то, что вы хотите. Возможно, вы должны узнать больше о encode & decode.


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

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

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

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

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


если вы запускаете интерпретатор python из оболочки в Linux или аналогичных системах (BSD, не уверен в Mac), вы также должны проверить кодировку по умолчанию для оболочки.

вызов locale charmap из оболочки (не интерпретатор Python) и вы должны увидеть

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

если это не так, и вы видите что-то другое, например

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

Python (по крайней мере, в некоторых случаях, таких как в моем) унаследует кодировку оболочки и не сможет печатать (некоторые? все?) символ Юникода. Собственная кодировка Python по умолчанию, которую вы видите и контролируете через sys.getdefaultencoding() и sys.setdefaultencoding() в этом случае игнорируется.

если вы обнаружите, что у вас есть эта проблема, вы можете исправить это с помощью

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(или выберите какую раскладку вы хотите вместо en_EN.) Вы также можете редактировать /etc/locale.conf (или какой-либо файл управляет определением локали в вашей системе), чтобы исправить это.