iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 7
0
Data Technology

30天python雜談系列 第 7

UnicodeError雜談之一———沒踩過這坑別說你用過python

python UnicodeError雜談之一

很常聽到python初學者會遇到有關UnicodeError的問題,就連比較資深的工程師,也會因為粗心大意而被UnicodeError搞昏頭,只能說在python世界裡打滾一定要被這個東西雷個幾次,想要真正的克服他,就要好好了解裏面的原理才是,今天我們就稍微深入剖析一下這一個議題,但在此之前,先來說一下究竟unicode是什麼東西。

首先要記得電腦裡存的所有資料本質上都是用1和0兩個數字組成的,也就是所謂的'二進制檔案',所以說一般常看到的txt文字檔,其實也都是一串1110010110011...所構成的,而這串1110010110011...必須透過特定編碼(ex.'100011' -> 'A', '100010' -> 'B')來識別,才能作為有意義的文字運作在程式中並能顯示在螢幕上給使用者看。

所以通常用記事本或是其他文本編輯軟體能開啟txt並能正確顯示文字,都是因為經過了正確的編碼,但當一個文字檔所用的編碼不是文本編輯軟體所採用的,那開啟後就會出現'亂碼'而無法了解其中內容。

而在早期每個地區都有自己的文字,在沒有一個人或一個團體出來提倡開發一個統一的編碼系統,當然就各地的編碼系統各自發展囉!所以會看到不同文字系統也常會有自己的編碼比如說繁體中文的Big5編碼、簡體中文的GB編碼、日文的 Shift-JS 編碼......等等。

但如果之後也沒有統一的編碼系統確實會對未來的各種軟體開發造成很大的困擾,光是要支援各種語言就必須死命研究各種編碼系統,既辛苦又沒什麼意義,所以現在有一個非營利組織The Unicode Consortium(統一碼聯盟)致力於提倡並維護unicode(萬國碼)作為一個現存電腦系統或是軟體標準編碼系統。

再來回到python的UnicodeError議題,為何常常看到python的程式跑出UnicodeError這個錯誤呢?是因為python在處理字串物件的時候,為了要維持一個字元真正的特性,比如說世界上每個不同的字都該有不同的編碼、一個字的長度就應該為一(通常一個編碼為了支援較大量的字元,1Byte的容量是不夠的,所以會給予一個字元超過1Byte的長度,因此長度會超過1),所以python會多提供一種字串類別,而這個類別是以unicode編碼作為基礎,如果你的python程式從網路或是檔案讀取了某些文字資料,想改成unicode編碼卻搞錯了這些文字資料的編碼,讓python無法有效轉換編碼,就會出現UnicodeError。

在處理字串時當然是建議將資料轉換為unicode編碼,當然如果基於某一些原因你想要以不同的編碼來做字串處理,python有提供轉碼函式可以使用,可以從unicode字串轉變為你想要的編碼,只是unicode編碼的字串和非unicode編碼的字串,他們分屬於不同類型的物件,這點要記得:

In python3 shell:
>>> a = '範例' # 這是unicode字串
>>> type(a)
<class 'str'>
>>> a = "範例".encode('utf-8') # encode函數將之轉為utf8字串
>>> type(a)
<class 'bytes'>

補充一下,如果是使用python2的朋友在python shell裡跑出的結果會不一樣,而且可能會很困惑,因為會在轉碼過程中會出現UnicodeDecodeError,所以應該要照以下範例進行:

In python2 shell:
>>> a = u'範例' # 這是unicode字串
>>> type(a) # 在python3的類別名稱為'str'
<class 'unicode'>
>>> a = u"範例".encode('utf-8') # encode函數將之轉為utf8字串
>>> type(a) # 在python3的類別名稱為'bytes'
<class 'str'>

因為python2不會在賦予字串常量給a的過程中轉碼為unicode編碼,而是遵照原本系統預設的編碼,像我的ubuntu 14.04預設編碼是'utf-8',如果要比照python3的範例以方便做比較,要先在字串前加上'u'前綴來解碼。

從結果來看,python2對於字串物件的分類名稱也和python3不一樣,改天會撥個時間說明一下python2和python3究竟有什麼不同。

要如何避免所謂的UnicodeError錯誤呢?有一個大方向是:"輸入文字(原編碼) -> python文字處理(unicode) -> 輸出文字(看自己要轉成什麼編碼)",進入python程式的文字統一都解碼成unicode字串,如果真的有需要用其他編碼處理,那可以用變數標明或是獨立在一個函式中進行處理,確保自己有條理的規範文字編碼,才是避開UnicodeError的不二法門。

至於實際會遇上UnicodeError的情境以及避免它的一些技術細節,就等明天再詳細解說吧!


上一篇
collection雜談之四———今天沒有副標題呵呵
下一篇
UnicodeError雜談之二———初探字符串與位元組的交互作用
系列文
30天python雜談30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言