# 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
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up