1. 程式人生 > >python檔案的編譯

python檔案的編譯

背景知識

  1. pyc檔案: .pyc 是一種二進位制檔案,是由 .py 檔案經過編譯後,生成一種byte code檔案。 .py 檔案變成 .pyc 檔案後,載入的速度有所提高,而且 .pyc 是一種跨平臺的位元組碼,是由python的虛擬機器來執行的,這個類似於JAVA或者.NET的虛擬機器的概念。 .pyc 的內容是跟python的版本相關的,不同版本編譯後的 .pyc 檔案是不同的,2.5編譯的 .pyc 檔案對於2.4版本的python是無法執行的。
  2. pyo檔案: .pyo 是優化編譯後的程式  python -O 原始檔 即可將源程式編譯為 .pyo 檔案。
  3. pyd檔案: .pyd 是python的動態連結庫。

 

為什麼要編譯Python檔案?

通常Python程式碼是不需要編譯就可以執行的,但Python其實也是有編譯的過程的,與Java和C#一樣Python只能執行位元組碼,Python只是將編譯過程隱藏起來了。將Python檔案編譯為 .pyc 或 .pyo 檔案有兩個目的:

  1. 由於 .py 檔案是可以直接看到原始碼的,所以如果是開發商業軟體的話就需要將 .py 檔案編譯為看不到原始碼的 .pyc 位元組碼檔案後再發布出去;
  2. 將 .py 檔案編譯為 .pyc 或 .pyo 檔案可以提高Python程式的載入速度,而且 .pyc 是一種跨平臺的位元組碼,由python的虛擬機器來執行;

python的編譯過程

  當我們通過下面的命令來執行一個Python程式時:(Linux中)


  
  1. Python test.py
  2. # test.py中的內容
  3. # --------------------------------------------------------
  4. #!/usr/bin/env python
  5. import mymodule
  6. mymodule.say( "hello")

Python直譯器其實並不一定會讀入 mymodule.py 檔案,它會嘗試讀取 mymodule.pyc 檔案或者 mymodule.pyo 檔案。如果都失敗了,或者 mymodule.py 檔案比 mymodule.pyc/mymodule.pyo 新,才轉而讀入 mymodule.py 檔案。Python只懂得解釋執行位元組碼,所以 mymodule.py 檔案讀入後第一件事就是先進行編譯。編譯的結果會被嘗試儲存到 mymodule.pyc 檔案中。Python的編譯實際上主要是進行文法分析,生成一個抽象語法樹,然後轉儲成位元組碼形式。這一點與Java有些相似,因為它們都生成位元組碼。

編譯Python檔案的方法(Linux)

  編譯 .py 檔案有以下幾種方式,所有這些方式都是使用了 py_compile 模組的 compile() 方法。同時我們可以使用 compileall 模組中的 compile_dir() 來編譯某個資料夾下面所有的 .py 檔案,以及可以使用 compile_path 來依次編譯 sys.path 指定路徑下的 .py 檔案。如果看過 compileall 模組的原始碼我們可以知道 compileall 編譯 .py 檔案其實還是呼叫了 py_compile 的 compile() 方法。

  在Linux環境下,可以通過寫一個bash指令碼編譯 .py 檔案,也可以直接通過命令列來編譯。(這裡僅介紹通過命令列來編譯的方法):

1. 生成單個的 .pyc  or  .pyo 檔案


  
  1. # 編譯成pyc檔案
  2. # ------------------------------------------------------
  3. python -m py_compile $filename # 其中,$filename是要編譯的python原始碼檔名
  4. # 編譯成pyo檔案
  5. # -------------------------------------------------------
  6. python -O -m py_compile $filename
  7. # 或者
  8. 1python -OO -m py_compile $filename
  9. 1
  10. 1 # 其中, + -O選項表示優化產生的位元組碼,優化程度由PYTHONOPTIMIZE(environment)的值來決定。 + -OO選項表示在-O優化的基礎上移除所有的doc-strings(文件文字)。

2. 批量生成 .pyc 檔案

  使用compileall模組可以批量編譯整個目錄下的Python原始碼檔案。


  
  1. # 函式定義
  2. compileall.compile_dir(dir, maxlevels= 10, ddir= None, force= False, rx= None, quiet= False, legacy= False, optimize= -1)
  3. # 用法:
  4. python -m compileall $dir

或者可以編寫指令碼來實現:


  
  1. import compileall
  2. compileall.compile_dir( '$dir')
  3. # 其中,$dir 為Python原始碼所在的目錄。