[Python] 出現 undefined symbol: PyUnicodeUCS4_AsEncodedString 錯誤
很久之前寫過一篇 自己編譯 Wide python 解決 Narrow python 的問題,
沒想到最近因為專案支援的另外一個產品在換平台,
因此又踩到了 narrow-python 的雷…
狀況是這樣的,他們從原本 CentOS 5.4 的 python 2.6,升級到 CentOS 7 的 python 2.7,
整合我們的東西的時候,就出現 pycurl 的錯誤:
>>> from tool.pycurl import pycurl Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: tool/pycurl/pycurl.so: undefined symbol: PyUnicodeUCS4_AsEncodedString
看起來是 pycurl.so 想要呼叫 PyUnicodeUCS4_AsEncodedString 這個函式,但是找不到,
可是以前他們用 python 2.6 的時候沒有這個問題…
而有另外一個產品也是用 CentOS 7 的 python 2.7,與我們整合時也沒有出現問題。
所以是怎麼一回事呢?
後來爬文得到一些靈感,分別檢查一下壞掉的那個產品的 python 與好的 python,
裡面的 PyUnicodeUCS 函式有哪些,果然發現壞掉的只有 PyUnicodeUCS2_AsEncodedString,
而好的那個就有我們需要的 PyUnicodeUCS4_AsEncodedString:
root@bad-python ~ $ nm -D /usr/lib64/libpython2.7.so | egrep "PyUnicodeUCS.*_AsEncodedString" 00000000000d71e0 T PyUnicodeUCS2_AsEncodedString root@good-python ~ $ nm -D /lib64/libpython2.7.so.1.0 | egrep "PyUnicodeUCS.*_AsEncodedString" 00000000000b7da0 T PyUnicodeUCS4_AsEncodedString
推想了一下,應該是我們自己在 CentOS 5.4 編譯 pycurl 時,
使用到系統預設的 python,而這系統預設的 python 是所謂的 narrow-python,
只有定義 PyUnicodeUCS2_AsEncodedString,
而出問題的外部產品在升級前用的 python 也是 narrow-python,所以沒問題。
但當升級到 CentOS 7 之後,我們使用系統預設的 wide-python 來編譯 pycurl,
但出問題的外部產品還是編譯出了 narrow-python,
導致 pycurl 想呼叫 PyUnicodeUCS4_AsEncodedString 卻找不到…
除了用 nm 查 export 出來的函式之外,
另一個檢查方法就是看 unichr(0x10000) 會不會有錯誤,有的就是 narrow-python:
>>> unichr(0x10000) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: unichr() arg not in range(0x10000) (narrow Python build)
或是看 sys.maxunicode 的值,65535 的就是 narrow-python:
>>> import sys >>> sys.maxunicode 65535
通知出問題的外部產品,在編譯 python 2.7 時,
加上 ./configure –enable-unicode=ucs4,就解決問題囉~
再次檢查這次編譯出來的 python,可以支援 unichr(0x10000),
sys.maxunicode 也可以達到最大值 0x10FFFF,的確是 wide-python 沒有錯:
>>> unichr(0x10000) u'\U00010000' >>> import sys >>> hex(sys.maxunicode) '0x10ffff'
參考資料:
How to find out if Python is compiled with UCS-2 or UCS-4?
Weird “undefined symbol: PyUnicodeUCS{2|4}_AsEncodedString” errors