回覆列表
  • 1 # 慎談奧秘

    在日常生活中,Python程式碼一般是不編譯的,幾個py檔案複製來就能用。再加上指令碼語言的名頭,有些不太瞭解Python的朋友就以為Python沒有編譯這個過程。其實,雖然Python是指令碼語言,但它與Java和C#一樣,只能執行位元組碼。只是Python將編譯過程隱藏起來,不大明顯而已。今天這篇筆記詳細記述一下Python的編譯過程以及一些技巧。

    我們一般使用這樣的命令執行一個python程式:

    C:\> python im.py

    其中,im.py檔案的內容是:

    #!/usr/bin/env pythonimport mymodulemymodule.say("hello")

    執行這一命令後,Python直譯器其實並不一定會讀入檔案,它會嘗試讀取檔案或者檔案。如果都失敗了,或者檔案比/新,才轉而讀入檔案。Python只懂得解釋執行位元組碼,所以檔案讀入後第一件事就是先進行編譯。編譯的結果會被嘗試儲存到檔案中。等一下會討論如何控制Python的編譯過程。

    雖然與C++/Java這樣的靜態語言一樣,採用了編譯(compile)這個術語,實際情況還是有所不同的。首先,最明顯的一點,Python編譯的最終結果不是機器碼,而是位元組碼。Python的編譯實際上主要是進行文法分析,生成一個抽象語法樹,然後轉儲成位元組碼形式了事。

    從上面的介紹可以發現Python的編譯與C++相去甚遠。不過倒與Java有些相像,因為它們都生成位元組碼。憑良心說,Java的編譯過程比Python先進很多。Java的直譯器在執行Java位元組碼的時候,會使用JIT,將迴圈操作等熱點轉化成為機器碼。所以有時候Java的效能能夠達到接近C++的級別。Python缺少JIT並非故意所為,而是缺少人力資源。現在已經有一個pysco的外部模組,據說能大大提高Python程式碼的速度,不過這個模組還沒有進入Python的官方程式碼。

    Python的位元組碼列表可以見此連結:http://www.python.org/doc/2.5.2/lib/bytecodes.html

    接下來,介紹一下如何"稍微"控制Python的編譯過程。只所以說是稍微,是因為無論何種情況,Python都會對位元組碼進行一些簡單最佳化(basic Peephole Optimization,詳情參見Python的原始碼。2.5版本的Python位於 ,2.7版本則位於)。這些最佳化不能透過環境變數或者命令引數將其禁用。比如:

    if True: return 1else: return 0

    會被最佳化成為:

    return 1

    更多的最佳化正被新增到Python原始碼內。只有三個引數能影響編譯時的最佳化:

    去除所有的語句,並將這個內建變數的值設定為。方法是執行Python的時候在命令列新增引數:

    python -O im.py

    除了第一條所做的事情,還去除所有docstring。方法是執行Python的時候在命令列新增引數:

    python -OO im.py

    預設的,對於一個模組,編譯後的位元組碼會被儲存到與原始碼相同的資料夾內。這樣就可以加速模組的載入速度。大多數使用Python的朋友們都寫過包含兩三個檔案的程式。通常可以發現除了.py檔案之外,資料夾內還會有.pyc檔案。檔案即是的位元組碼。如果執行Python的命令列包含了或者引數,Python會將最佳化後的位元組碼儲存到檔案。想要禁止生成.pyc或者.pyo檔案,可以在執行Python的時候,在命令列裡新增引數:

    python -B im.py

    還可以設定環境變數:

    c:\> set PYTHONDONTWRITEBYTECODE=x

    看完上面三條說明,有的朋友可能會疑問,"-O"和"-OO"引數真的就幹那三件事?不幸的是,還真是如此。至少在Python2.5的時候就是這樣。所以加"-O"引數並不能明顯最佳化Python的執行速度。這兩個選項的真正作用是區分除錯版本和發行版本。在程式中可以儘量多增加一些語句,以便程式設計師在除錯階段發現一些隱藏的錯誤。而在釋出時,將這些語句去除。如果你的軟體是商業軟體的話,加上"-OO"引數可以讓別人看不清內部函式的用途,增加一些破解的難度。有了這些,誰還說Python不能寫商業軟體?

    說到商業軟體,不得不說到反編譯工具。很神奇的一件事,Python內建了反編譯的模組!囧rz,使用方法也很簡單:

    >>> import mymodule >>> import dis >>> dis.dis(mymodule) #打印出反編譯的結果

    反編譯後的程式碼與組合語言接近,所以想要破解Python商業軟體還是有一定難度的。據說還有一些工具能夠反編譯出漂亮的Python原始碼,我並沒有親見。

    --------------河南新華

  • 中秋節和大豐收的關聯?
  • 醬肉的做法,自制醬肉怎麼做好吃,自制醬肉的家常做法?