2017-04-23 31 views
2

這是flabbergasting和非常令人沮喪,請幫助。爲什麼可以解碼u' xe5'而不是' xe5'?

>>> a1 = '\xe5' # type <str> 
>>> a2 = u'\xe5' # type <unicode> 
>>> ord(a1) 
229 
>>> ord(a2) 
229 
>>> print a2.encode('utf-8') 
å 
>>> print a1.encode('utf-8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128) 

如果a1和a2具有相同的值,爲什麼不能同時編碼?

我必須使用一個外部API,它返回a1表單上的unicode數據,這使得它無用。 Python顯然堅持認爲<str>鍵入的字符串只能包含ASCII字符或拒絕編碼它們。它徹底打破了我的申請。

+0

您是否嘗試過使用它編碼的字符集對其進行解碼? –

+0

嗯......原來數據編碼爲latin-1。根據我能找到的任何技術細節,我無法合理化正確的猜測。我不知道Python或者終端或者其他什麼都決定使用latin-1。我只是做了一個幸運的猜測。 –

+0

它沒有。它是通過它產生的任何方式進行編碼的。 –

回答

3

您只能編碼Unicode字符串。如果你在一個字節串上調用encode,Python會首先嚐試解碼,使用默認編碼 - 因此是錯誤。 (請注意,這種混淆行爲僅發生在Python 2中,它已在Python 3中被刪除)。

+0

沒有辦法設置字節串的編碼嗎?數據來自與LANG = en_US.utf8一起運行的終端。 –

+0

更好:沒有辦法將字節字符串轉換爲unicode類型而不運行任何轉換?畢竟,這些數組完全是字節完全相同的。 –

0

python2中,字符串是ASCII,而在python3中的字符串是Unicode。

ASCII字符可能只有一個介於0和127之間的值。 但是Unicode字符可能會有更高的值。

python2

>>> a = '\x7f' 
>>> a.encode('utf-8') 
'\x7f' 
>>> a = '\x80' 
>>> a.encode('utf-8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128) 

python3

>>> a = '\x7f' 
>>> a.encode('utf-8') 
b'\x7f' 
>>> a = '\x80' 
>>> a.encode('utf-8') 
b'\xc2\x80' 

,這個作品在python2u前綴的原因是因爲你明確地指出, 「這是一個Unicode字符串」。


這可能是值得閱讀了使用Unicode的一個更深入的瞭解,python2


要利用(破碎的)API,最好轉換返回的st振鈴成一個字節陣列,但注意,這將不會在python3工作。

>>> a = '\xe5' 
>>> b = bytearray(a) 
>>> b[0] 
229 

請記住,\xe5是不是一個有效的Unicode(UTF-8)字符...要存儲在UTF-8編碼字符串值0xE5,你需要存儲兩個字節:0xC3 0xA5

0

讓我拆掉你的困惑。我們首先從strunicode之間的區別開始。在Python 2.X:

  1. str是一個打印爲ASCII儘可能8位字符(1字節)的字符串。str實際上是一個字節序列,與Python 3.X中的bytes等效。 * str沒有編碼。
  2. unicode是一個Unicode代碼點的字符串。

其次,編碼根據Python documentation指:

「的用於轉換Unicode字符串轉換爲一個字節序列規則被稱爲編碼」。

然後,問自己這個問題:編碼str這是已經是一個字節序列是否有意義?答案是不。因爲str已經是一個字節序列。但編碼unicode確實有意義,爲什麼?因爲它是一串Unicode字符代碼點(即U + 00E4')。

0

Ignacio建議從其實際編碼(而不是ascii,但什麼?)解碼字節字符串讓我嘗試使用拉丁-1,儘管我認爲它應該是utf-8。這工作!

我從Python2.7 curses模塊中獲取數據。我最好的猜測是問題出現在某處。終端的編碼是UTF-8,但現在可以使用。

相關問題