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 时错误是“ can’t decode”。巨蟒在引擎盖下面做什么?

325156 次浏览

始终从 Unicode 到字节的 编码
在这个方向,你可以选择编码方式

>>> 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“打地鼠”,那么了解数据级别发生的情况非常重要。这里用另一种方式来解释:

  • Unicode 对象已经被解码了,您永远不会希望对其调用 decode
  • 一个 bytestring 对象已经被编码了,您永远不会想要在它上面调用 encode

现在,在字节字符串上看到 .encode时,Python2首先尝试将其隐式转换为文本(unicode对象)。类似地,当在 unicode 字符串上看到 .decode时,Python2会隐式地尝试将其转换为字节(一个 str对象)。

这些隐式转换就是为什么在调用 encode时可以得到 UnicodeDecodeError的原因。这是因为编码通常接受 unicode类型的参数; 当接收到 str参数时,在用另一种编码重新编码之前,有一个隐式解码到 unicode类型的对象中。这个转换选择一个默认的“ ascii”解码器 ,给出编码器内部的解码错误。

事实上,在 Python3中,方法 str.decodebytes.encode甚至不存在。为了避免这种普遍的混乱,他们的离开是一种(有争议的)尝试。

或者不管 sys.getdefaultencoding()提到什么代码,通常都是“ ascii”

如果使用 Python < 3,则需要告诉解释器您的 通过使用 u作为字符串文字的前缀,字符串文字是 Unicode:

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 如何操作

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

encode将 unicode 对象转换为 string对象。但是这里您已经在 string对象上调用了它(因为您没有 u)。因此,python 必须首先将 string转换为 unicode对象。所以它相当于

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

但是解码失败了,因为字符串不是有效的 ascii。所以你才会收到无法解码的投诉。

使用 u"你好".encode('utf8')对 Unicode 字符串进行编码。 但是如果你想表示 "你好",你应该解码它,就像:

"你好".decode("utf8")

你会得到你想要的。也许你应该学习更多关于编码和解码。

你可以试试这个

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

或者

您还可以尝试以下操作

在.py 文件的顶部添加以下行。

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

在使用 Unicode 的情况下,有时也可以忽略特殊字符,例如 encode('utf-8')

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

或作为 这里建议的 something.decode('unicode_escape').encode('ascii','ignore')

在这个例子中不是特别有用,但是当不能转换一些特殊字符时,可以在其他场景中更好地工作。

或者你可以考虑 使用 replace()替换特定字符

如果您是从 Linux 或类似系统(BSD,不确定是否是 Mac)上的 shell 启动 python 解释器,那么您还应该检查 shell 的默认编码。

从 shell (而不是 python 解释器)调用 locale charmap,您应该会看到

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

如果情况并非如此,你看到的是别的东西,例如。

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

Python 将(至少在某些情况下,例如在我的)继承 shell 的编码,并且将不能打印(一些?全部?)Unicode 字符。在本例中忽略了 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(或管理系统中区域设置定义的任何文件)来纠正这个问题。