Unicode已經解決了很多問題。知曉ISO-8859-*和CP437帶來的混亂(當然對於非西方語言來說更糟糕)的人都可以證明這一點。當然,這些天他們正在做一項有的益工作——編碼表情符號。
除表情符號之外,一切並不那麼順暢。今日Python 3帶來的痛苦更是一言難盡。
Python決定將Unicode完全整合到語言中。聽起來很不錯吧?
但眾多問題也隨之而來。
例如,將帶有智慧引號的“播客”標題轉為以ASCII編碼會引致python錯誤,導致gPodder(一款開源的播客接收器,採用Python和PyGTK開發,可幫助管理播客RSS供稿,並自動下載所需要的播客資料)經常透過回溯退出。接著pexpect檔案會告訴你用logfile = sys.stdout 來顯示與虛擬終端的互動。就是這個在這些天引發了一個錯誤。
檔案名的處理可謂糟糕透頂。我最近處理了20年前當UTF-8還未成為檔案名標準時的資料。這些檔案名在UNIX上仍然有效,可以用tar命令進行壓縮或解壓。但當你試圖將檔案名以字串的形式儲存,編碼錯誤便接踵而至。要想讓Python程式正確地支援所有有效的Unix檔案名,必須使用“bytes”而不是字串,這可真夠煩人的。所有Python程式正確的機率又能達到多少呢?我敢打賭,不會高的。
我最近正在處理mtree生成的資料,它使用八進位制轉義來處理檔案名中的特殊字元。我認為這對於Python會很容易。結果…
-
許多錯誤的解答 ——對於某些值,你會得到一個編碼錯誤。甚至那個頁面上的正則運算式解決方案也不起作用。
-
甚至存在更多錯誤的解答
第二個連結提到了一個未記錄的函式—— codecs.escape_decode ,可正確解決這一問題。我最終不得不這樣做:
而且,無論做什麼,不要輕易寫 if filetype=="file" ——這總被求值為False,因為 "file" 在邏輯運算時不同於 b"file" 。呃…好吧,我承認,自己一開始沒註意到,踩過這坑…
因此,如果希望在Python中正確處理Unix檔案名,你必須:
-
有一個完全避免Python字串的處理路徑。
-
使用 sys.{stdin,stdout}.buffer 而不是簡單的 sys.stdin/stdout 。
-
必須將檔案名以位元組形式提供給各種函式。詳情請參閱 PEP 0471:“與os模組中的其他函式一樣,scandir() 接受一個bytes或str類作為路徑引數,並傳回與路徑型別相同的 DirEntry.name 和 DirEntry.path 屬性。但是,強烈建議使用str型別,因為這樣可以確保Unicode編碼的檔案名得到跨平臺支援(在Windows上,Python 3.3開始,就已經不支援bytes編碼的檔案名了)。”所以,如果你想跨平臺,那就更糟了,因為不能在Unix上使用str也不能在Windows上使用bytes。
更新:你想在命令列上接收檔案名嗎?我會把這個爛攤子交給你的。環境呢? 甚至都不清楚呢!
小編說兩句:這事兒真不怪Python,題主這種“處理了20年前當UTF-8還未成為檔案名標準時的資料”的任務,平時誰會碰到,這種任務當然需要題主對編碼系統足夠瞭解才能完成了……題主發發牢騷,別怨Python……
英文原文:http://changelog.complete.org/archives/9938-the-python-unicode-mess
譯者:盈韜
來源:Python程式員
《Linux雲端計算及運維架構師高薪實戰班》2018年11月26日即將開課中,120天衝擊Linux運維年薪30萬,改變速約~~~~
*宣告:推送內容及圖片來源於網路,部分內容會有所改動,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。
– END –