[Python] 自己編譯 Wide python 解決 Narrow python 的問題
其實也是網友在 使用 mechanize 自動登入網站 留言裡,
提到了遇到了奇怪的錯誤訊息,
才知道 python 2.x 有所謂的 narrow python 的問題…
不懂 narrow python 的人可以參考一下:
– ValueError: unichr() arg not in range(0x10000) (narrow Python build)
基本上 python 2.x 預設編譯狀態就是 narrow python,
代表一個 unicode 字元是用兩個 byte 來表示的 (也就是 ucs2)~
這平常沒什麼問題,但是如果用到超過 0xFFFF 的 Unicode 字元時,
就會出事了:
>>> unichr(0x10000) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: unichr() arg not in range(0x10000) (narrow Python build)
Python 3.x 全面支援 Unicode,所以連 unichr() 這個函式都沒了,
chr() 就可以處理這種 Unicode 字元了~
可是如果我就是要用 Pytho 2.x 怎麼辦呢?
只好自己重新編譯 Python 囉~
1. 下載 Python 原始檔
我這邊用的是 python 2.6.8,也可以再去官網找更新的 2.x 版本:
wget http://www.python.org/ftp/python/2.6.8/Python-2.6.8.tgz
tar zxvf Python-2.6.8.tgz
cd Python-2.6.8
2. 設定 Python 組態
在執行 configure 時要注意加上 –enable-unicode=ucs4 才能編譯出 wide python,
我這邊還加上了 –with-threads 來支援 threading 的處理:
./configure --with-threads --enable-unicode=ucs4
如果不想把 python 裝到系統目錄裡 /usr 的話,可以指定 –prefix 選項,
例如下面的指令會將 python 的目錄設定在 /home/testuser/python2.6_wide:
./configure --prefix=/home/testuser/python2.6_wide --with-threads --enable-unicode=ucs4
3. 編譯 Python
執行 make 來編譯:
make
接著執行 make install 就能將 python 安裝到 /usr/bin 下面了,
但如果系統已經有一個 python 的話,這樣做很有可能會蓋掉系統的 python,
其他相依於這個 python 的套件有可能會掛掉…
一種解決方法是用上面提到的 –prefix 指定目錄,這樣 make install 會裝到指定目錄去,
不用擔心會汙染到系統的目錄:
make install
另一種是利用 python 提供的 altinstall 方式,
這種方式會將 python 裝到 /usr/local/bin 目錄下,
而且會加上版本號,例如 /usr/local/bin/python2.6,
而函式庫的目錄也是分開的 (跑到 /usr/local/lib/python2.6),不會跟系統的互相影響:
sudo make altinstall
用 which 看一下系統預設的 python 和用 make altinstall 的 python 各在哪裡:
[testuser@localhost Python-2.6.8]$ which python /usr/bin/python [testuser@localhost Python-2.6.8]$ which python2.6 /usr/local/bin/python2.6
這個 python2.6 就是我們剛編譯出來的 wide python 版本,
立刻來試試看它能不能支援超過 0xFFFF 的 Unicode 字元吧:
>>> unichr(0xFFFF) u'\uffff' >>> print unichr(0x10000) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\U00010000' in position 0: ordinal not in range(128)
嗯… unichr() 可以接受超過 0xFFFF 的 Unicode 字元了,
可是 print 還是會出現錯誤…
這邊跟 sys.stdout 的編碼有關,有興趣的人再看一下 python: PrintFails 這個連結吧~
(其實是我已經有點懶得再追了… 遇到了這個問題的話再說吧 :P)