2012-03-10 87 views
94

我真的很困惑。我试图编码,但错误说can't decode...Python - 'ascii'编解码器无法解码字节

>>> "你好".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”前缀的错误。我只是想知道为什么当调用编码时错误是“无法解码”。 Python在做什么?

回答

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

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

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

相当于但是因为该字符串不是有效的ASCII解码失败。这就是为什么你会抱怨无法解码。

+29

那么解决方案是什么?特别是如果我没有字符串文字,我只是有一个字符串对象。 – 2013-03-12 07:57:52

+2

@JonTirsen,你不应该编码一个字符串对象。一个字符串对象已经被编码。如果您需要更改编码,则需要将其解码为一个unicode字符串,然后将其编码为所需的编码。 – 2013-03-12 16:24:36

+17

因此,从上面清楚地说明你可以''你好'.decode('utf-8')。encode('utf-8')' – deinonychusaur 2013-07-25 08:18:27

44

总是编码从unicode到012字节的
在这个方向上,你可以选择编码

>>> 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就可以了。
  • 一个字符串对象已经被编码了,你永远不想调用encode就可以了。

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

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

事实上,在Python 3的方法str.decodebytes.encode甚至不存在。他们的撤除是一个[有争议]的尝试,以避免这种常见的混淆。

...或任何编码sys.getdefaultencoding()提及;通常这是 'ASCII'

+0

那么你的意思是Python在编码之前解码字节串? – thoslin 2012-03-10 05:28:49

+0

@thoslin,我添加了更多细节。 – wim 2014-06-02 18:00:32

+0

什么是_,为什么您的打印语句缺少括号? – NoBugs 2017-09-30 03:24:56

6

如果你正在使用Python < 3,你需要告诉你的string literal is Unicode by prefixing it with a 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

+3

如果你正在编码一个字符串,它为什么会抛出解码错误? – MxyL 2012-03-10 05:36:42

1

您使用u"你好".encode('utf8')来编码unicode字符串。 但是,如果你想代表"你好",你应该解码它。就像:

"你好".decode("utf8") 

你会得到你想要的。也许你应该更多地了解编码&解码。

33

你可以试试这个

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

或者

您也可以尝试以下在你的.py文件的顶部

添加以下行。

# -*- coding: utf-8 -*- 
+5

尽管Python中的编码很麻烦,但这是一个非常危险的想法。如果你这样做,你*会*导致意想不到的问题。正如其他答案中所述,改正您的数据。 – davidism 2016-12-16 19:08:19

+1

@davidism - 为什么/如何? – Xodarap777 2017-06-07 16:38:53

相关问题