Кодек 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
(или какой-либо файл управляет определением локали в вашей системе), чтобы исправить это.