您好,登錄后才能下訂單哦!
小編給大家分享一下Python編譯相關知識有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Python是一門能快速開發的解釋型語言
Python和Java的解釋方式對比
Java:源代碼 -> 編譯成class -> Jvm解釋運行
Python:源代碼 -> Python解釋器解釋運行
事實上,Python和Java的解釋方式是相同的,只是我們表面上看Python是直接解釋源代碼,而實際上python解釋器只會加載字節碼。細心的小伙伴肯定發現了這一點,當我們import某個模塊時,總是會在模塊所在的目錄創建一個__pycache__目錄,里面存放著被加載模塊的字節碼文件
編譯源代碼有以下作用:
源代碼保護(算法保護)
防止用戶篡改源代碼解釋器加載代碼速度加快
Python的幾種文件類型
py:Python控制臺程序的源代碼文件
pyw:Python帶用戶界面的源代碼文件
pyx:Python包源文件
pyc:Python字節碼文件
pyo:Python優化后的字節碼文件
pyd:Python的庫文件(Python版DLL)、在Linux上是so文件
pyc和pyo的生成方法
pyc的作用是用來跨平臺使用的,和Java中的Class文件類似。pyc文件是一種字節碼文件,可以加快Python解釋器的加載速度,當然也可以用來做簡單的防源碼泄露保護。
pyo則是優化過后的字節碼文件,不過pyo更像編譯型語言里的中間文件。
我們可以通過Python提供的py_compile模塊來進行源代碼的編譯。
py_compile模塊只提供3個方法,分別是有關編譯異常PyCompileError、有關編譯compile、有關程序入口main
我們要用到的是compile方法,compile原形如下:
compile(file, cfile=None, dfile=None, doraise=False, optimize=-1)
有5個參數:
file:必選參數,要編譯的源文件
cfile:編譯后的文件,默認在源文件目錄下的__pycache__/源文件名.解釋器類型-python版本.字節碼類型
### 例如:__pycache__/abc.cpython-34.pyo
dfile:錯誤消息文件,默認和cfile一樣
doraise:是否開啟異常處理,默認False
optimize:優化字節碼級別
optimize為1時,優化字節碼級別為最高 -1和0:設置pyc優化級別 1和2:設置pyo優化級別 數字越小,優化級別越高
準備源文件a.py和b.py,內容相同,就是一句print("python")代碼
編寫編譯腳本:
import py_compile py_compile.compile(file = "a.py",cfile = "a.pyc",optimize=-1) py_compile.compile(file = "b.py",cfile = "b.pyo",optimize=1)
運行后可以看到已經成功編譯成字節碼文件了,分別為a.pyc和b.pyo。
嘗試運行這2個字節碼文件:
python a.pyc python a.pyo
字節碼文件成功運行。
也可以直接通過Python加載模塊來運行:
#編譯成pyc
python -m py_compile 源代碼
#編譯成pyo
python -O -m py_compile 源代碼
這確實可以簡單地保護我們的代碼,同時似乎看起來像是加密的效果,但是要注意,這不是加密,只是把源碼變成優化后的字節碼而已,如果想要獲得源碼,我們一樣可以通過逆向編譯來得到源碼,目前有專門逆向Python字節碼的工具存在。
如果需要編譯整個目錄內的所有源代碼,請參考Python compileall
pyd可以讓我們的代碼更安全
如果真的想要保護代碼,為何不考慮把它變成python擴展模塊?(目前還沒有pyd被反編譯的消息)
pyd是Python中的擴展模塊,相當于windows的dll,不同的是pyd只供python調用而已。
實際上,大部分的包、小模塊都是以pyd形式發布的。
如果特別感興趣的小伙伴可以深入研究下setuptools和distutils
在把源代碼轉換成功pyd之前,我們需要用到Cython包。
pip list | findstr "Cython"
檢查是否安裝了Cython,沒有請pip install Cython安裝即可
編譯pyd步驟1:生成C代碼
import Cython.Build
#導入Build模塊
Cython.Build.cythonize("a.py")
#a.py轉換成C代碼
cythonize運行完成之后,無異常的情況下會在a.py的目錄下創建一個a.c文件,同時會返回一個distutils.extension.Extension對象列表
一定要注意的是:如果在Python Shell測試,一定要用絕對路徑,否則會ValueError異常,cythonize不會從sys.path中讀路徑。
編譯pyd步驟2:利用distutils生成pyd擴展模塊
此時我們可以用distutils包來編譯成我們要的pyd模塊
編譯a.py成pyd
import Cython.Build
import distutils.core
a = Cython.Build.cythonize("a.py")
#返回distutils.extension.Extension對象列表
distutils.core.setup(
name = 'pyd的編譯',#包名稱
version = "1.0",#包版本號
ext_modules= a,#擴展模塊
author = "Happyran", #作者
author_email='happyran163@163.com' #作者郵箱
)
python 執行編譯的腳本 build
或
python 執行編譯的腳本 build_ext
此時會在編譯腳本所在目錄生成一個build目錄,里面存著C語言的.def文件和.o文件,還有我們要的pyd文件
批量編譯pyd文件的誤區
此時我們已經生成了1個pyd文件,如果我們是擴展包/模塊的開發者,怎么批量編譯呢?
總有人會犯錯,例如以下2個例子:
a = Cython.Build.cythonize("a.py")
b = Cython.Build.cythonize("b.py")
distutils.core.setup(
...,
ext_modules= [a,b]
)
這樣做嗎?NO......
a = Cython.Build.cythonize("a.py")
a.append(Cython.Build.cythonize("b.py"))
distutils.core.setup(
...,
ext_modules= a
)
還是這樣?
犯這樣的錯原因卻是因為:
a = Cython.Build.cythonize("a.py")
type(a)
提示<class 'list'>
沒錯,Cython.Build.cythonize返回的是一個列表,里面只有1個distutils.extension.Extension對象
會報錯,需要1個Extension或者是2個元組
批量編譯pyd
方法1:提取我們要的Extension對象
import Cython.Build
import distutils.core
a = Cython.Build.cythonize("a.py")[0] #提取Extension對象
b = Cython.Build.cythonize("b.py")[0]
distutils.core.setup(
name = 'pyd的編譯', #包名稱
version = "1.0", #包版本號
ext_modules= [a,b], #被擴展的模塊
author = "Happyran", #作者
author_email='happyran163@163.com' #作者郵箱
)
方法2:轉換成C代碼后再進行Extension對象實例化
import Cython.Build
import distutils.core
Cython.Build.cythonize("a.py")
Cython.Build.cythonize("b.py")
distutils.core.setup(
name = 'pyd的編譯', #包名稱
version = "1.0", #包版本號
ext_modules= [distutils.core.Extension('a',["a.c"]),distutils.core.Extension('b', ['b.c'])], #被擴展的模塊
#[
#distutils.core.Extension('a',["a.c"]),
#distutils.core.Extension('b', ['b.c'])
#]
author = "Happyran", #作者
author_email='happyran163@163.com' #作者郵箱
)
pyc和pyo相對而言安全性較低,pyd是目前解決Python開發中代碼安全性最優的一個方案。
但是要注意一點:無論是pyc還是pyo、pyd,都是跟著Python版本走的,不要指望Python2.7的東西在Python3上完美運行。
PS:如果遇到running build...提示,刪掉build目錄重新編譯即可。
以上是“Python編譯相關知識有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。