2012-08-16 107 views
5

顯然,我能做到這一點在Python 2.7:字節字符串字面與非ASCII字符

value = '國華' 

好像Python是用編碼來編碼字符的字符串字面量爲字節的字符串中。什麼是編碼?那是sys.getdefaultencoding()中定義的編碼,源文件的編碼還是別的?

感謝

+1

源文件或命令行中是否存在該行?另外,你是否真的想學習Python 2.7中編碼的複雜性(與2.6和3.x稍有不同),還是隻是想解決一個可以通過在前面粘貼'u'解決的問題報價? – abarnert 2012-08-16 18:33:43

+0

我其實正在嘗試學習Python 2.7編碼的複雜性。這是在一個源文件中,但我也有興趣知道在命令提示符下這是不同的。 – Flavien 2012-08-16 19:25:06

+1

Python 2.7表示不這樣做,但如果您對CPython 2.7所做的事情感興趣,無論如何......源文件中引號內的字面字節(例如'\ xe5 \ x9c \ x8b \ xe8 \ x8f \ xaf')被存儲爲一個字節字符串。由於源文件的編碼聲明可能與'sys.getdefaultencoding()'不同,因此您可能無法安全地解釋它,但字節在那裏。如果兩種編碼是相同的,終端也是如此,並且編碼可以處理這些字符,那麼甚至可以「打印價值」並查看您的期望。這是你想要的,還是有更多? – abarnert 2012-08-16 20:48:07

回答

7

getdefaultencoding與源文件或終端的編碼沒有關係。它是用於將字節字符串隱式轉換爲Unicode字符串的編碼,並且在Python 2.X上應始終爲'ascii'(Python 3.X上的'utf8')。

Python的2.X,你在沒有聲明編碼的腳本代碼行產生一個錯誤:

SyntaxError: Non-ASCII character '\x87' in file ... 

實際的非ASCII字符可能會有所不同,但不會沒有編碼工作宣言。編碼聲明要求在Python 2.X上使用非ASCII字符。編碼聲明必須匹配源文件的編碼。例如:

# coding: utf8 
value = '國華' 

當保存爲CP936產生:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte 

當編碼是正確的,該字節串中的字節是字面上是源文件中,所以它將包含編碼字符的字節。當Python解析一個Unicode字符串時,這些字節會使用聲明的源編碼解碼爲Unicode。注意區別打印UTF-8字節串和CP936控制檯上的Unicode字符串時:

# coding: utf8 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

輸出:

鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf' 
國華 u'\u570b\u83ef' 

字節字符串包含3字節的UTF-8編碼的兩個字符,但由於cp936終端無法理解字節序列,所以顯示不正確。 Unicode打印正確,並且該字符串包含從源文件的UTF-8字節解碼的Unicode代碼點。

注聲明和使用該終端相匹配的編碼時的區別:

# coding: cp936 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

輸出:

國華 '\x87\xf8\xc8A' 
國華 u'\u570b\u83ef' 

字節串的內容是現在的2字節CP936編碼兩個字符('A'相當於'\ x41'),並且由於終端理解了cp936字節序列,所以顯示正確。 Unicode字符串包含與前一個示例中的兩個字符相同的Unicode代碼點,因爲源字節序列使用聲明的源編碼解碼爲Unicode。

如果腳本具有正確的源編碼聲明和使用Unicode字符串爲文本,它將顯示正確的字符終端編碼無關。如果終端不支持字符而不是顯示錯誤的字符,它會拋出UnicodeEncodeError

最後說明:Python 2.X默認爲'ascii'編碼,除非另有聲明,並且如果編碼支持它們,則字節字符串中允許使用非ASCII字符。 Python 3.X默認使用'utf8'編碼(所以請確保保存在該編碼中或另外聲明),並且而不是允許在字節字符串中使用非ASCII字符。

如果終端字體支持字符。
如果終端編碼支持字符。

1
value = b'國華' 

是沒有意義的(在b在Python 2.x的是隱含的) - 你爲什麼要一個字節字符串包含字符? Python可以簡單地複製終端/編輯器使用的任何編碼字節。你想要的是一個字符字符串:

value = u'國華' 

在源代碼文件(而不是一個交互式shell),不通過將下面的行添加到文件的開頭忘記declare the encoding

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

很明顯,Python設計師並不認爲這是毫無意義的,因爲他們認爲它是有效的。你沒有真正回答我的問題,當我運行該行時,Python使用哪種編碼,我如何從代碼中找出問題? – Flavien 2012-08-16 19:28:54

+0

當您在交互式shell或具有編碼聲明的源文件中運行該行時,或者...什麼? – abarnert 2012-08-16 19:38:27

+2

@字節文字中的@Flavien非ASCII字符是歷史文物。沒有使它們有效的代碼,它們只是被意外接受,並且可以追溯到Python沒有明確字節與字符串語義的時間。字節文字中的非ASCII字符不再有效;他們已經[從Python 3中移除](http://ideone.com/f1iLN)。運行該行時,Python不使用任何編碼。該文件是一串字節,字面值產生的字節對象也是如此。 – phihag 2012-08-16 19:56:10