2012-03-10 161 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

相關問題