Python打包編譯工具Pyinstaller與Nuitka特性超詳細(xì)對(duì)比
概要
當(dāng)我們發(fā)布Python項(xiàng)目時(shí),有時(shí)為了隔離運(yùn)行環(huán)境的差異 或者 不希望以源碼的形式發(fā)布,一種常用的方法是將Python項(xiàng)目打包/編譯成二進(jìn)制文件(更具體的討論在Python項(xiàng)目加密 中),打包編譯的工具有很多,其中PyInstaller 和 Nuitka 是目前最主流的兩個(gè)工具。它們都能將 .py 文件打包成無需安裝 Python 環(huán)境即可運(yùn)行的二進(jìn)制程序,但其底層機(jī)制、性能表現(xiàn)和適用場(chǎng)景存在顯著差異。
結(jié)合實(shí)際的項(xiàng)目實(shí)踐,本文從功能原理、特性異同、性能對(duì)比及實(shí)際選型建議等 詳細(xì)對(duì)比 PyInstaller 與 Nuitka 的核心特性,供有需要的伙伴參考以項(xiàng)目需求做出更合理的技術(shù)選型。
簡(jiǎn)介
Pyinstaller
PyInstaller 是一個(gè)流行且成熟的 Python 打包工具,能Python 腳本及其依賴項(xiàng)(包括解釋器、標(biāo)準(zhǔn)庫(kù)、第三方包等)封裝成單個(gè)可執(zhí)行的二進(jìn)制文件或目錄結(jié)構(gòu)。它通過分析字節(jié)碼來靜態(tài)追蹤導(dǎo)入關(guān)系,并將所有必要資源捆綁到運(yùn)行時(shí)環(huán)境中。
Nuitka
Nuitka (讀作 努伊特卡) 是一個(gè) 真正意義上的Python 編譯器,它將 Python 代碼轉(zhuǎn)換為優(yōu)化的 C / C++ 代碼,再通過gcc/msvc等編譯鏈編譯鏈接成可執(zhí)行文件。
Python項(xiàng)目
提供一個(gè)Python Project,Python項(xiàng)目 SLOC (一個(gè)衡量項(xiàng)目源碼量的指標(biāo)——源碼行數(shù),統(tǒng)計(jì)時(shí)會(huì)刨除文檔注釋、空行、虛擬環(huán)境、非.py文件等無效因素影響) 2700+,屬于中小型項(xiàng)目(一般代碼量處于 1000~10000 的Python Project劃分為中型項(xiàng)目),不含GUI相關(guān)依賴,文件結(jié)構(gòu)形如:
| -- main.py # 項(xiàng)目入口文件 | -- settings.py # 項(xiàng)目運(yùn)行設(shè)置 | -- framework # 項(xiàng)目核心 | -- basic # 項(xiàng)目基礎(chǔ)文件 | -- release # 發(fā)布 | -- scripts # 其他腳本 | -- cis # CI/CD相關(guān) | -- venv # 項(xiàng)目虛擬環(huán)境
打包命令分別為:
# 執(zhí)行下述命令前先cd到項(xiàng)目根目錄下,并激活虛擬環(huán)境 # pyinstaller 與 nuitka 的安裝均通過pip install直接安裝即可,以Windows平臺(tái)為例 # Pyinstaller # 打包成單文件 pyinstaller -F main.py --workpath .\release\build --distpath .\release\output --clean --specpath .\release\windows # 打包成單目錄 pyinstaller -D main.py --workpath .\release\build --distpath .\release\output --clean --specpath .\release\windows # ps: pyinstaller更常用的一種打包方式是指定.spec文件打包 # Nuitka # 打包成單文件 nuitka --onefile --windows-console=disable --follow-imports --output-dir=.\release\output --clean-cache=all --lto=yes main.py # 打包成單目錄 nuitka --standalone --windows-console=disable --follow-imports --output-dir=.\release\output --clean-cache=all --lto=yes main.py # nuitka 在打包時(shí)支持指定編譯相關(guān)的特性,比pyinstaller更靈活
特性剖析
相同點(diǎn)
- pyinstaller與nuitka均支持單文件/單目錄打包,單文件打包出來的二進(jìn)制文件相對(duì)單目錄更“緊湊”,但是在運(yùn)行時(shí)單文件的內(nèi)存開銷與單目錄不相上下,甚至反超;
- 單文件打包出來的二進(jìn)制文件,運(yùn)行時(shí)后臺(tái)會(huì)同時(shí)駐留至少兩個(gè)同名的進(jìn)程(例如編譯出來的是my_app.exe,啟動(dòng)后任務(wù)管理器里至少有兩個(gè)my_app.exe 進(jìn)程),其中一個(gè)內(nèi)存開銷明顯比較小的是打包編譯工具夾帶的引導(dǎo)器(Bootstrap Loader),負(fù)責(zé)先把單文件解壓到臨時(shí)目錄、設(shè)置運(yùn)行環(huán)境(資源解壓、環(huán)境管理、進(jìn)程監(jiān)控、權(quán)限管理等)后再啟動(dòng)真正的主進(jìn)程。所以單文件產(chǎn)物運(yùn)行時(shí)并非真正意義上的“單進(jìn)程”。
- 單文件打包出來的產(chǎn)物如果運(yùn)行中崩潰,并且使能了進(jìn)程崩潰后自動(dòng)重啟將會(huì)反復(fù)在臨時(shí)目錄里解壓資源,最后會(huì)把磁盤寫爆,但單目錄產(chǎn)物運(yùn)行時(shí)完全不存在這種問題,因?yàn)樗夸浝锓诺谋旧砭褪墙鈮汉蟮膬?nèi)容,并且運(yùn)行時(shí)不需要,所以相對(duì)單文件產(chǎn)物來說運(yùn)行更穩(wěn)定,如果不是為了分發(fā)方便,更推薦by 目錄打包編譯;
- 對(duì)于Python項(xiàng)目來說,只要安裝了一個(gè)第三方模塊,不管有沒有在項(xiàng)目中import,都可能會(huì)影響到打包編譯出來的固件大小,并且一般會(huì)使得打包編譯的產(chǎn)物變大;(為什么是可能而不是一定,是根據(jù)第三方模塊而定,像額外安裝一個(gè)Cython就不會(huì)影響到打包編譯出來的產(chǎn)物,但是安裝airtest / numpy等就會(huì)有影響,即便在項(xiàng)目中沒有用到)
差異點(diǎn)
- 不管是打包成單文件還是單目錄,pyinstaller的打包過程都明顯比nuitka快,從打包編譯的原理上也好理解,后者多了一道 先轉(zhuǎn)碼再編譯 的過程;
- Nuitka編譯出來的產(chǎn)物(不管是單文件還是單目錄,下同)理論上應(yīng)該比Pyinstaller更精簡(jiǎn),但是在筆者上面的示例項(xiàng)目中,nuitka編譯出來的產(chǎn)物比Pyinstaller大了 ~1.5MB,經(jīng)分析可能是因?yàn)轫?xiàng)目并不是特別大,且不含GUI或者諸如OpenCV、paddleocr等大型第三方依賴,所以nuitka編譯的優(yōu)勢(shì)沒有體現(xiàn)出來;
- 上面提到單文件打包出來的固件運(yùn)行時(shí)會(huì)先解壓到臨時(shí)目錄,Pyinstaller解壓到了C盤下的%TEMP%/_MEI* 目錄,nuitka打包時(shí)允許自定義臨時(shí)目錄的位置,但是均解決不了崩潰后資源回收的問題;
- Pyinstaller打包出來的產(chǎn)物可以被反“打包”(可通過 pyinstxtractor 提取 pyc)反轉(zhuǎn)碼成Python源碼,但nuitka幾乎不可能實(shí)現(xiàn)反編譯;
- nuitka編譯出來的產(chǎn)物運(yùn)行效率完爆Pyinstaller打包出來的產(chǎn)物;
- nuitka在打包編譯的時(shí)候控制更靈活,可以控制編譯行為,比如開啟性能優(yōu)化等;
最后來張對(duì)比圖:

場(chǎng)景選型
- 小型項(xiàng)目(SLOC < 1000),快速交付驗(yàn)證:pyinstaller
- 中型項(xiàng)目(SLOC 1000~10000),帶GUI / 圖像處理 / 網(wǎng)絡(luò)服務(wù),
- 大型項(xiàng)目(SLOC > 10000),優(yōu)選nuitka。
總之,如果更注重高性能、安全性、防逆向、運(yùn)行時(shí)資源消耗小、商業(yè)化,優(yōu)選nuitka;如果追求快速迭代、生態(tài)成熟穩(wěn)定、兼容性好,優(yōu)選pyinstaller。
總結(jié)
PyInstaller 與 Nuitka 代表了 Python 打包領(lǐng)域的兩種哲學(xué):
- PyInstaller 是“打包專家”——擅長(zhǎng)整合現(xiàn)有資源,快速交付可用成果;
- Nuitka 是“編譯先鋒”——致力于將 Python 提升至系統(tǒng)級(jí)語言的執(zhí)行效率。
對(duì)于大多數(shù)開發(fā)者而言,PyInstaller 是首選入門工具;而對(duì)于追求性能、安全與專業(yè)形象的團(tuán)隊(duì),Nuitka 正逐漸成為下一代標(biāo)準(zhǔn)。
技術(shù)選型沒有銀彈,只有最適合業(yè)務(wù)場(chǎng)景的選擇。理解工具本質(zhì),方能游刃有余。
到此這篇關(guān)于Python打包編譯工具Pyinstaller與Nuitka特性超詳細(xì)對(duì)比的文章就介紹到這了,更多相關(guān)Python打包編譯Pyinstaller與Nuitka內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)提取COCO,VOC數(shù)據(jù)集中特定的類
這篇文章主要介紹了python實(shí)現(xiàn)提取COCO,VOC數(shù)據(jù)集中特定的類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Python使用random.shuffle()隨機(jī)打亂字典排序
本文主要介紹了Python使用random.shuffle()隨機(jī)打亂字典排序,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
python pkg_resources模塊實(shí)例詳解
在Python中,pkg_resources模塊是setuptools包的一部分,用于從安裝的Python包中檢索各種元數(shù)據(jù),本文介紹python pkg_resources模塊,感興趣的朋友跟隨小編一起看看吧2026-03-03
Python Opencv使用ann神經(jīng)網(wǎng)絡(luò)識(shí)別手寫數(shù)字功能
這篇文章主要介紹了opencv(python)使用ann神經(jīng)網(wǎng)絡(luò)識(shí)別手寫數(shù)字,由于這里主要研究knn算法,為了圖簡(jiǎn)單,直接使用Keras的mnist手寫數(shù)字解析模塊,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
解決python錯(cuò)誤提示:TypeError: expected string or&nb
這篇文章主要介紹了解決python錯(cuò)誤提示:TypeError: expected string or bytes-lik問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

