# Python 執行原理 Byte Code 電腦不能夠識別高級語言,所以需要一個翻譯機把高級語言轉變成電腦能識別的機器語言,這個過程分成編譯型語言與解釋型語言。 * 編譯型語言在執行程序前,會先通過一個編譯的過程,編釋器(compiler)把程序轉變成機器語言,運行時就不需翻譯就可以執行,如C語言。 * 直譯型(解釋型)語言就是不透過編譯的過程,而是在程序運行時,通過解釋器(intepreter)對程序逐行翻譯,再直接運行,如 Ruby 跟 Python。 ### *.py 執行過程 以 Python3 為例,執行一個python3 file.py 檔,此時發生: 1. Interpreter 會將 Python Source Code file.py interpret 成 Byte Code(儲存 Byte 型態的資料)。 2. Byte Code 會再被 Virtual Machine compile 成 Machine Code 以及 Executable Code 等。 3. 最後Virtual Machine 會觸發 CPU 以及系統調度來執行這份程式碼要處理的事。 **示意圖:**  ### Byte Code 為什麼設計這樣的流程產生一個中間程式碼(Byte Code),而不直接生成Excutable File? 提供更靈活架構方便轉換、提昇嫁接性,如 Byte Code 可以對接 Java 的 Virtual Machine,達成跨平台、系統的效果。 可作到「一行一行執行」的概念,不花費許多資源做通到底的編譯,提昇開發效率。 常見支援 Python 的 Interpreters : CPython (C 寫成): 最多人使用 PyPy (RPython 寫成) Jython (Java 寫成) ### *.pyc 用途 Byte Code 除了被 C Virtual Machine 讀取並執行外,Python 會把常使用的 Byte Code 寫進 Disk 儲存起來,變成 *.pyc 檔。通常在__pycache__資料夾下,import的library會在LIB pyc是一種二進位制檔案,是由py檔經過直譯後生成的檔案,是 Byte Code 在 Python 裡的一個實現。pyc的內容跟python版本相關,不同版本直譯後的pyc檔案不同。 為什麼需要 .pyc 檔? 主要的理由是加速運行,py檔案變成pyc檔案後,提高載入的速度。而且pyc是一種跨平臺的位元組碼,由python的虛擬機器來執行。 *.pyc 參與Python執行過程: * 當 Python 程序運行時,解釋的結果會暫時保存在記憶體中的 PyCodeObject中,當 Python 程序結束時,Python解釋器會把PyCodeObject寫入到pyc的檔案裡。 * 當 Python 程序第二次運行時,首先會在硬碟中尋找 .pyc檔,如果有找到,並且發現Python的原始碼被異動,就會檢查 *.py文件的更新時間與 *.pyc 文件的更新時間,如果 *.py的時間比較新,代表檔案有更新,則重複解釋器的過程;反之,就直接載入。 ### *py轉成 *.pyc py_compile 模組把py檔案編譯為pyc檔案 #### 生成單個*.pyc 把某py檔案編譯為pyc檔案。 ```python= import py_compile py_compile.compile(r'hi.py') print('done') ``` 函式compile(file, cfile, dfile, doraise)說明: * file:需要編譯的py檔案的路徑。 * cfile:表示編譯後的pyc檔名和路徑,預設為直接在file檔名後加c或o,o表示優化的位元組碼。 * dfile:把在錯誤資訊中顯示的file名稱用dfile名稱替換。 * doraise:True或False,如果為True,如果編譯檔案出錯會引發一個PyCompileError;否則預設顯示在sys.stderr中,而不會引發異常。 * optimize:用於編譯的最佳化層級,有效值為-1,0,1,2。-1表示當前解譯器的最佳化層級。 #### 批量生成*.pyc 把某目錄及其子目錄下的py檔案編譯為pyc檔案。 用命令列編譯一個目錄下的檔案,如:python -m compileall /root/src/ ```python= import compileall compileall.compile_dir(r'D:\game') print('done') ``` 函式compile_dir(dir, maxlevels, ddir, force, rx, quiet)說明: * dir:需要編譯的資料夾位置。 * maxlevels:需要遞迴編譯的子目錄的層數,預設是10層。 * ddir:把在錯誤資訊中顯示的file用ddir替換。 * force:如果為True,即使現在的pyc檔案是最新的,也會再強制編譯一次,pyc檔案中包含時間戳,python編譯器會根據時間來決定,是否需要重新生成一次pyc檔案。 * rx:為正則表示式,可過濾符合條件的目錄進行編譯。 * quiet:如果為True,則編譯後不會在標準輸出中印出資訊。 修改python原始碼中的opcode檔案(Python39\include\opcode.h & Python39\Lib\opcode.py),新生成的pyc檔,將無法被其他版本python所使用,可防止被反編譯破解。 如何使用修改後的opcode? 更改opcode的相關檔案,再安裝python,刪除舊有的pyc檔,便可使用不同opcode的python環境。 **Reference:** https://www.796t.com/content/1508990186.html https://saucer-man.com/information_security/825.html https://medium.com/citycoddee/python%E9%80%B2%E9%9A%8E%E6%8A%80%E5%B7%A7-5-python-%E5%88%B0%E5%BA%95%E6%80%8E%E9%BA%BC%E8%A2%AB%E5%9F%B7%E8%A1%8C-%E7%9B%B4%E8%AD%AF-%E7%B7%A8%E8%AD%AF-%E5%AD%97%E7%AF%80%E7%A2%BC-%E8%99%9B%E6%93%AC%E6%A9%9F%E7%9C%8B%E4%B8%8D%E6%87%82-553182101653
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.