2015年12月20日 星期日

Python 2.x/3.x 中的 str、bytes 以及 unicode

前言


在初學 Python 時,總是對於Python對於文字編碼的處理,感到疑惑!尤其版本的差異造成認知上的混淆,前一陣子,因為我有中文文字處理的相關需求,發現對於編碼概念以及處理的重要性,浪費了不少時間,故以此篇記錄提醒自己。


Python2.x/3.x 字元序列型別差異

在 python3.x 裡,有兩種型態來表示字元序列:
  1. bytes:原始的八位元值(二進位資料、常見的編碼為 UTF-8)
  2. str:即unicode
而 python2.x 裡,則是另外兩種型態來表示字元序列:
  1. str:原始的八位元值(二進位資料、常見的編碼為 UTF-8)
  2. unicode


編碼(encoding)與解碼(decoding)概念

在 python2.x 中,通常會在檔案的開頭給定 # -*- coding: utf-8 -*- ,因為 python2.x 中會以ASCII 編碼來解讀程式原始碼,所以不給的話,我們打中文會出現錯誤,然而在 python3.x 中則預設原始碼必須是 UTF-8 編碼。

假使我們要將 python3.x 的 str 以及 python2.x 的 unicode 進行二進位資料轉換,必須使用 encode,相反要將二進位資料轉換為 unicode 則需使用 decode。

在一些書籍以及網站上,通常會建議程式的核心應以 unicode 型別,並且不對字元的編碼格式進行預設,因為如此一來才能讓我們接受各種不同的文字編碼,但在輸出時必須確保我們是以 UTF-8 編碼(通常)。

在 python 2.x 我們可以撰寫 helper function 來確保字串型態,如下:

helper function


Python3.x 寫入與讀取檔案可能遇到之問題

因為在 python3.x 版,對於 open 函式有encoding為 utf-8 的預設,因此若要解決 TypeError,請務必使用 rb、wb 等二進位模式開啟檔案,而在 python 2.x 雖然本身已是二進位預設開啟,但若同樣使用 rb、wb,可以減少對於版本差異而發生的錯誤。


進階參考

在Mac上,放置 binary file 的相關概念

前一陣子剛好有一個需求,就是將他人所編譯好的 binary file(我看到的副檔名為 unix executable),在 command-line 執行,傻傻的我一直對著該檔雙擊,結果都因為沒送進任何參數,而立馬結束。

因此開始思考怎麼在 command line 上,讓 binary file 如同指令般被我操作,而所幸找到了一些文章,也更認識了在Mac上環境變數的一些小竅門。

大致上心得如下:在 command line 下,打 echo $PATH,查看路徑變數存了哪一些,每個以 : 為分隔,我們也可以用 export 來設置新變數路徑,而通常可以將 binary file 放在 /usr/local/bin 下,而因為 /usr/local/bin 在 /usr/bin 及 /bin 之後,因此若有相同名稱,會先以系統層級為基準,深入的瞭解與解法可以查看此篇:mac-os-x-conventional-places-where-binary-files-should-live

平常時都是用 Homebrew 來管理電腦上的套件,而像是這種自行下載 binary file 的經驗,感覺也相當不錯 XD