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) 

我知道如何避免string上带有“u”前缀的错误。 我只是想知道为什么错误是“无法解码”时调用编码。 Python在做什么?

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

encode将一个unicode对象转换为一个string对象。 但是在这里你已经在一个string对象上调用它(因为你没有你)。 所以Python必须首先将string转换为一个unicode对象。 所以它相当于

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

但解码失败,因为该string是无效的ascii。 这就是为什么你会抱怨无法解码。

总是从unicode 编码为字节。
在这个方向上, 你可以select编码

 >>> 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
  • 一个string对象已经被编码了,你永远不想调用它的encode

现在,看到一个字节string上的.encode ,Python 2首先尝试隐式地将其转换为文本(一个unicode对象)。 同样的,在看到unicodestring上的.decode时,Python 2会隐式地尝试将其转换为字节(一个str对象)。

这些隐式转换是为什么当你调用encode时可以得到Unicode Decode Error 。 这是因为编码通常接受一个unicodetypes的参数; 当接收到str参数时,在用另一个编码对其进行重新编码之前,会隐式解码unicodetypes的对象。 这个转换select一个默认的“ascii”解码器,给你一个编码器内的解码错误。

事实上,在Python 3中, str.decodebytes.encode方法都不存在。 他们的搬迁是一个有争议的尝试,以避免这种常见的混乱。

…或任何编码sys.getdefaultencoding()提到; 通常这是'ascii'

你可以试试这个

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

要么

您也可以尝试以下操作

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

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

如果你使用Python <3,你需要告诉解释器你的string是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')来编码一个unicodestring。 但是如果你想代表"你好" ,你应该解码它。 就像:

 "你好".decode("utf8") 

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

如果你正在处理Unicode,有时候而不是encode('utf-8') ,你也可以尝试忽略特殊字符,例如

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

something.decode('unicode_escape').encode('ascii','ignore')如这里所build议的 。

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

或者,您可以考虑使用replace()replace特定的字符 。