顯然,我能做到這一點在Python 2.7:字節字符串字面與非ASCII字符
value = '國華'
好像Python是用編碼來編碼字符的字符串字面量爲字節的字符串中。什麼是編碼?那是sys.getdefaultencoding()
中定義的編碼,源文件的編碼還是別的?
感謝
顯然,我能做到這一點在Python 2.7:字節字符串字面與非ASCII字符
value = '國華'
好像Python是用編碼來編碼字符的字符串字面量爲字節的字符串中。什麼是編碼?那是sys.getdefaultencoding()
中定義的編碼,源文件的編碼還是別的?
感謝
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字符。
如果終端字體支持字符。
如果終端編碼支持字符。
value = b'國華'
是沒有意義的(在b
在Python 2.x的是隱含的) - 你爲什麼要一個字節字符串包含字符? Python可以簡單地複製終端/編輯器使用的任何編碼字節。你想要的是一個字符字符串:
value = u'國華'
在源代碼文件(而不是一個交互式shell),不通過將下面的行添加到文件的開頭忘記declare the encoding:
# -*- coding: utf-8 -*-
很明顯,Python設計師並不認爲這是毫無意義的,因爲他們認爲它是有效的。你沒有真正回答我的問題,當我運行該行時,Python使用哪種編碼,我如何從代碼中找出問題? – Flavien 2012-08-16 19:28:54
當您在交互式shell或具有編碼聲明的源文件中運行該行時,或者...什麼? – abarnert 2012-08-16 19:38:27
@字節文字中的@Flavien非ASCII字符是歷史文物。沒有使它們有效的代碼,它們只是被意外接受,並且可以追溯到Python沒有明確字節與字符串語義的時間。字節文字中的非ASCII字符不再有效;他們已經[從Python 3中移除](http://ideone.com/f1iLN)。運行該行時,Python不使用任何編碼。該文件是一串字節,字面值產生的字節對象也是如此。 – phihag 2012-08-16 19:56:10
源文件或命令行中是否存在該行?另外,你是否真的想學習Python 2.7中編碼的複雜性(與2.6和3.x稍有不同),還是隻是想解決一個可以通過在前面粘貼'u'解決的問題報價? – abarnert 2012-08-16 18:33:43
我其實正在嘗試學習Python 2.7編碼的複雜性。這是在一個源文件中,但我也有興趣知道在命令提示符下這是不同的。 – Flavien 2012-08-16 19:25:06
Python 2.7表示不這樣做,但如果您對CPython 2.7所做的事情感興趣,無論如何......源文件中引號內的字面字節(例如'\ xe5 \ x9c \ x8b \ xe8 \ x8f \ xaf')被存儲爲一個字節字符串。由於源文件的編碼聲明可能與'sys.getdefaultencoding()'不同,因此您可能無法安全地解釋它,但字節在那裏。如果兩種編碼是相同的,終端也是如此,並且編碼可以處理這些字符,那麼甚至可以「打印價值」並查看您的期望。這是你想要的,還是有更多? – abarnert 2012-08-16 20:48:07