[Python] 不同版本 python 編譯出的 pyc 不相容

[Python] 不同版本 python 編譯出的 pyc 不相容

用不同版本的 python 編譯出來的 pyc 是不能相容的,

這件事在剛學 python 時就已經知道,本來也沒什麼問題,

沒想到最近產品想要從 CentOS 6.2 改換成 7.0,

所以預設的 python 從 2.6 變成了 2.7,

導致我們之前用 python 2.6 編譯出來的 pyc,在 python 2.7 是不能執行的~

 

現在我們的解決之道,就是找到正確的 python 版本,

來執行對應的 pyc…

雖然蠻麻煩的,不過似乎也沒什麼其他的解法了,

Decompile 回原本的 py 是一種方式,但是反組譯是不保證成功的…

 

來看一下不同版本的 pyc 的差異吧~

假設有下面一個非常簡單的 python 檔:

print("hello")

 

用 py_compile 編譯成 pyc:

python2.6 -m py_compile testpyc.py
python2.7 -m py_compile testpyc.py

 

編譯好之後,用 python2.6 是不能執行 python2.7 編譯出來的 pyc,

反之亦然,會出現 Bad magic number in .pyc file 的錯誤:

testuser@localhost ~ $ python2.6 testpyc_26.pyc
hello
testuser@localhost ~ $ python2.6 testpyc_27.pyc
RuntimeError: Bad magic number in .pyc file
testuser@localhost ~ $ python2.7 testpyc_27.pyc
hello
testuser@localhost ~ $ python2.7 testpyc_26.pyc
RuntimeError: Bad magic number in .pyc file

 

這裡的 magic number 是 pyc 檔頭的最前面 4 個 byte,

不過後兩個 byte 固定是 0d 0a~

每個 python 版本都有不同的 magic number,

可以參考 stackoverflow 這篇文章看看每個 python 版本對應的 magic number~

(或是 python 裡的 import.c)

用 python 也可以很容易的讀出前面兩個會變動的 byte:

testuser@localhost ~ $ python -c 'print open("testpyc_26.pyc").read(2).encode("hex")'
d1f2
testuser@localhost ~ $ python -c 'print open("testpyc_27.pyc").read(2).encode("hex")'
03f3

 

關於 pyc 的結構,The structure of .pyc files 這篇有更多的說明~

如果用檔案比對軟體,比較一下這兩個 pyc,會發現只有檔頭不同:

Screen Shot 2015-07-17 at 1.05.51 AM  

 

這樣是不是代表只要修改一下檔頭的 magic number,

就可以讓 python2.7 執行 python2.6 編譯出來的 pyc 呢?

雖然我們曾經想過這件事情,不過很快就被推翻了,

只要找一個稍微複雜一點的 py 編譯一下,

就能發現越複雜的 py 對應的 pyc 檔的內容就越不同~

像我只是在 py 裡面多加上 print os.listdir(“.”),pyc 的差異點就增加了:

Screen Shot 2015-07-17 at 1.25.10 AM  

 

結論是:還是只能用正確的 python 去執行 pyc 了… =_=

看是要執行後失敗再換別的,還是根據檔頭的 magic number 判斷都行…

 

(本頁面已被瀏覽過 1,816 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料