2015-01-21 51 views
1

一個簡單的例子unicode的變量:Python的解碼與非ASCII字符或不

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import sys 
import traceback 

e_u = u'abc' 
c_u = u'中國' 

print sys.getdefaultencoding() 
try: 
    print e_u.decode('utf-8') 
    print c_u.decode('utf-8') 
except Exception as e: 
    print traceback.format_exc() 

reload(sys) 
sys.setdefaultencoding('utf-8') 
print sys.getdefaultencoding() 
try: 
    print e_u.decode('utf-8') 
    print c_u.decode('utf-8') 
except Exception as e: 
    print traceback.format_exc() 

輸出:

ascii 
abc 
Traceback (most recent call last): 
    File "test_codec.py", line 15, in <module> 
    print c_u.decode('utf-8') 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) 

utf-8 
abc 
中國 

一些問題困擾了我幾天,當我想徹底瞭解編解碼器在Python中,我想確保我認爲是正確的:

  1. 根據ascii de故障編碼,u'abc'.decode('utf-8')沒有錯誤,但是u'中國'.decode('utf-8')有錯誤。

    我覺得做u'中國'.decode('utf-8'),Python的檢查,發現當u'中國'是unicode的,所以儘量做到u'中國'.encode(sys.getdefaultencoding()),這樣會導致問題,而例外的是UnicodeEncodeError,不是錯誤的時候解碼。

    u'abc''abc'(< 128)的代碼點相同,所以沒有錯誤。

  2. 在Python 2.x中,python內部存儲變量值如何?如果字符串< 128中的所有字符視爲ascii,如果> 128,則視爲utf-8

    In [4]: chardet.detect('abc') 
    Out[4]: {'confidence': 1.0, 'encoding': 'ascii'} 
    
    In [5]: chardet.detect('abc中國') 
    Out[5]: {'confidence': 0.7525, 'encoding': 'utf-8'} 
    
    In [6]: chardet.detect('中國') 
    Out[6]: {'confidence': 0.7525, 'encoding': 'utf-8'} 
    

回答

1

簡短的回答

你必須使用encode(),或離開它。不要使用帶有unicode字符串的decode(),這沒有任何意義。此外,sys.getdefaultencoding()在這裏沒有任何幫助。

漫長的答案,第1部分:如何正確地做到這一點?

如果定義:

c_u = u'中國' 

然後c_u已經是一個unicode字符串,也就是說,它已經從字節的字符串解碼(源文件),以Unicode字符串由Python解釋器,使用您的-*- coding: utf-8 -*-聲明。

如果執行:

print c_u.encode() 

您的字符串將被編碼回UTF-8和字節串發送到標準輸出。請注意,這通常是爲您自動發生,所以您可以簡化這:

print c_u 

長的答案,第2部分:這有什麼錯c_u.decode()?

如果執行c_u.decode(),Python會

  1. 試圖將對象轉換(即你的unicode字符串),以字節串
  2. 嘗試,如果你的對象是擺在首位一個Unicode字符串到字節字符串解碼爲unicode字符串

請注意,這並沒有任何意義 - 你只將它轉換回來。但爲什麼會失敗?那麼,這是一個Python的奇怪的功能,第一步驟(1),即從unicode字符串任何轉換爲字節串,通常採用sys.getdefaultencoding(),這反過來又默認爲ASCII字符集。換句話說,

c_u.decode() 

大致解釋到:

c_u.encode(sys.getdefaultencoding()).decode() 

這就是爲什麼它失敗。

注意的是,雖然你可能會改變這種默認的編碼,不要忘記其他第三方庫可能包含類似的問題,如果默認編碼爲ASCII不同可能打破。

話雖如此,我堅信,Python的是,如果他們沒有在第一時間定義unicode.decode()更好。 Unicode字符串已經被解碼,再次解碼它們毫無意義,特別是Python的方式。

+0

我知道應該使用'encode',我的問題是,爲什麼在u'abc」使用解碼都沒有問題,而且我認爲是正確的? – 2015-01-21 09:22:09

+0

請參閱我的答案的第二部分,其中描述了unicode.decode()在內部的行爲。這應該清楚爲什麼'u'abc'.decode()'意外地工作。 – vog 2015-01-21 09:38:33

+1

你說的第2部分,我認爲錯誤:'從unicode字符串的任何隱式轉換爲字節字符串,總是使用ASCII字符set.'。請參閱我問的示例代碼,如果將默認編碼更改爲utf-8,則可以。 – 2015-01-21 14:12:33