微觀層次變化和2to3無法充分解決的最大問題是從字節到Unicode的默認字符串類型。
如果你的代碼需要對編碼和字節I/O做任何事情,它需要大量的手工努力才能正確地進行轉換,所以那些必須是字節的東西仍然是字節,並且在右邊適當地解碼階段。您會發現某些字符串方法(特別是format()
)和庫調用需要Unicode字符串,因此您可能需要額外的解碼/編碼循環才能將字符串用作Unicode,即使它們只是字節。
這並不是因爲某些Python標準庫模塊被粗略地轉換爲2to3而沒有適當關注字節/ unicode /編碼問題,所以它們自己會犯錯字符串類型是合適的。其中一些正在被淘汰,但至少從Python 3.0到3.2,您將面臨來自像urllib,email和wsgiref等需要了解字節編碼的軟件包的混淆和潛在的錯誤行爲。
您可以在每次編寫字符串時小心謹慎地解決問題。將u''
字符串用於固有字符的任何內容,b''
字符串用於任何真正爲字節的字符串,''
用於「默認字符串」類型,其中無關緊要,或者您需要匹配庫調用的字符串使用要求。
不幸的是,b''
語法只在Python 2.6中引入,所以這樣做會切斷較早版本的用戶。
ETA:
有什麼區別?
哦,我的。好...
一個字節包含0-255範圍內的一個值,可能表示二進制數據(例如圖像內容)或某些文本的負載,在這種情況下必須選擇標準將一組字符映射到這些字節中。這些「編碼」標準中的大多數以相同的方式將正常的'ASCII'字符集映射到字節0-127,因此在Python 2中使用字節字符串僅用於ASCII純文本處理通常是安全的。
如果你想要使用ASCII字符串之外的字符串中的任何字符,您遇到了麻煩,因爲每種編碼都將不同的字符集映射到其餘字節值128-255,並且大多數編碼無法映射每個可能的字符到字節。這是所有這些問題的根源,您將一個文件從一個語言環境加載到另一個語言環境的Windows應用程序中,並且所有重音或非拉丁字母都會更改爲錯誤的文件,從而導致無法讀取的混亂。 (又名'mojibake')。
還有'多字節'編碼,它試圖通過使用多個字節來存儲每個字符來將更多字符裝入可用空間。這些東西是爲東亞語言環境引入的,因爲有很多中文字符。但也有UTF-8,一個更好設計的現代多字節編碼,可以容納每字符。
如果您正在處理多字節編碼中的字節字符串 - 今天您可能會這樣做,因爲UTF-8使用非常廣泛;實際上,在現代應用中不應該使用其他編碼 - 那麼你就會遇到更多的問題,而不是跟蹤你正在使用的編碼。 len()
將以字節爲單位告訴你長度,而不是以字符爲單位的長度,如果你開始建立索引和改變字節,你很可能會將多字節序列分成兩部分,產生一個無效序列,並且一般都會混淆所有內容。
因此,Python 1.6及更高版本具有原生Unicode字符串(拼寫爲u'something'
),其中字符串中的每個單元都是字符而不是字節。你可以len()
他們,切片他們,取代他們,正則表達他們,他們將永遠行事適當。對於文本處理任務來說,它們毫無疑問更好,這就是爲什麼Python 3使它們成爲默認字符串類型的原因(不必在''
之前放置u
)。
問題在於很多現有的接口(如Windows以外的操作系統上的文件名或HTTP或SMTP)主要是基於字節的,並且具有指定編碼的單獨方式。所以當你處理需要字節的組件時,你必須小心地將你的unicode字符串正確地編碼爲字節,而在Python 3中,你必須在某些不需要的地方明確地執行它。
這是一個內部實現細節,Unicode字符串在內部爲每個單元存儲「兩個字節」的存儲空間。你永遠不會看到存儲;你不應該用字節來考慮它。無論Python選擇如何在內存中表示它們,您正在使用的單位在概念上都是字符。
...撇開:
這並不完全正確。在Python的「狹義構建」中,像Windows構建一樣,Unicode字符串的每個單元在技術上不是字符,而是UTF-16的「代碼單元」。對於基本多語言平面中的字符,從0x0000到0xFFFF,您不會注意到任何區別,但如果您使用的是16位範圍以外的字符,那麼在'星體平面'中的字符,您會發現兩個單位,而不是一個單位,而且,當你切片時,你又冒險分割一個角色。
這是非常糟糕的,並且發生的原因是Windows(以及其他人,如Java)在Unicode超過65,000個字符限制之前以UTF-16作爲內存存儲機制。但是,使用這些擴展字符仍然非常少見,任何Windows上的用戶都會習慣於破解很多應用程序,因此這對您來說可能並不重要。
在'廣泛構建'上,Unicode字符串由真正的字符'代碼點'單元構成,所以即使是BMP之外的擴展字符也能夠一致且輕鬆地處理。支付的代價是效率:每個字符串單位在內存中佔用四個字節的存儲空間。
說到字節和Unicode字符串,有什麼區別?只有字節字符串每個字符使用一個字節,而unicode使用兩個字節? – 2010-08-06 18:02:49
「」「UTF-8 ...在現代應用程序中不應該使用其他編碼」「,除非你的政府要求其他的東西,例如, 'gb18030' :-) – 2010-08-07 01:20:31
這是關於字節字符串和Unicode之間差異的很好的解釋。我或多或少熟悉ASCII與Unicode,但是(顯然)我並不熟悉Python(尤其是3.x)如何處理它們。我希望我可以多次投票;) – 2010-08-12 16:53:21