介紹
- 開發完的python工具,想發送給親朋好友使用,順便得到一些好棒棒的讚賞,這時候,你需要pyinstaller ,它可以幫你打包相關的
python script
及library
,編譯出一個執行檔,提供使用者直接操作使用。- 罷特!仍有需要注意的地方,可參考底下的 小結1-跨平台問題 。
準備
- 強烈建議使用python virtualenv來建構你的開發環境,系統乾淨之外,在執行
pyinstaller
打包時,可以避免打包不必要的library進來,減少執行檔的大小。
安裝
pip install pyinstaller
- 個人推薦3.4版
基礎指令
- 安裝完後,咱們先來看看他有哪些功能,開啟terminal 輸入
pyinstaller --help
,簡單來說,就是pyinstaller + [功能指令] + [你的python script]
usage: pyinstaller [-h] [-v] [-D] [-F] [--specpath DIR] [-n NAME]
[--add-data <SRC;DEST or SRC:DEST>]
[--add-binary <SRC;DEST or SRC:DEST>] [-p DIR]
[--hidden-import MODULENAME]
[--additional-hooks-dir HOOKSPATH]
[--runtime-hook RUNTIME_HOOKS] [--exclude-module EXCLUDES]
[--key KEY] [-d [{all,imports,bootloader,noarchive}]] [-s]
[--noupx] [-c] [-w]
[-i <FILE.ico or FILE.exe,ID or FILE.icns>]
[--version-file FILE] [-m <FILE or XML>] [-r RESOURCE]
[--uac-admin] [--uac-uiaccess] [--win-private-assemblies]
[--win-no-prefer-redirects]
[--osx-bundle-identifier BUNDLE_IDENTIFIER]
[--runtime-tmpdir PATH] [--bootloader-ignore-signals]
[--distpath DIR] [--workpath WORKPATH] [-y]
[--upx-dir UPX_DIR] [-a] [--clean] [--log-level LEVEL]
scriptname [scriptname ...]
...省略 ...
What to generate:
-D, --onedir Create a one-folder bundle containing an executable
(default)
-F, --onefile Create a one-file bundled executable.
--specpath DIR Folder to store the generated spec file (default:
current directory)
-n NAME, --name NAME Name to assign to the bundled app and spec file
(default: first script's basename)
- 功能落落長,沒關係,我們先學會下面的基本指令,建立我們的自信心 :100:
縮寫指令 | 完整指令 | 說明 |
---|---|---|
-D | --onedir | default:將所有的東西打包到一個資料夾中 |
-F | --onefile | 將所有的東西打包到一個檔案中,ex: windows的exe檔 |
--specpath | 輸出spec 檔案到指定的資料夾 | |
-n Name | --name Name | 打包的檔名 |
準備
- 為了測試
pyinstaller
厲害的地方,咱們來安裝個GUI工具來測試pip install PySide2
,讓我們打包的程式,點兩下有個UI可以跑出來 :+1: - 開啟一個
main.py
貼上以下的程式碼:
import sys, os
from PySide2.QtWidgets import QApplication, QLabel
from PySide2.QtCore import Qt
if __name__ == "__main__":
# 下面指令是告訴QT,我要設計一個600(w)x100(h)大小的Label widget,上面顯示著`OKLA`
app = QApplication(sys.argv)
label = QLabel('OKLA')
label.setFixedSize(300, 100)
label.setAlignment(Qt.AlignHCenter|Qt.AlignVCenter)
label.show()
sys.exit(app.exec_())
python main.py
執行看看,會跑出如下的UI畫面
Test1: 快速打包(產出執行檔+相依的檔案)
- 開啟terminal到資料夾下,並輸入以下指令
pyinstaller main.py
- 開始編譯
-
- 開始編譯
出現successfully編譯成功啦!
檢查資料夾,會多出資料夾
build
、dist
,以及main.spec
檔案 | 說明 |
---|---|
build資料夾 | 編譯執行檔過程的產物,先不須理會 |
dist 資料夾 | :accept: 編譯的結果,也就是我們要的執行檔 |
main.spec | 其實是根據使用者針對pyinstaller有使用到的功能,整理成spec 檔,進階的方式也可以進去裡面修改,會在下一次介紹。 |
- 開啟
dist/main
資料夾,你會發現到一個main
執行檔
Test2: 完整打包(打包出一個檔案)
為了避免編譯出錯,我們先將剛剛的
dist
及build
資料夾砍掉,在輸入以下指令,並將他命名為justRunMe
pyinstaller -F -n justRunMe main.py
, 打包比較久,先吃塊蛋糕:cake:
編譯完後,打開
dist
資料夾,剛剛的程式都被打包成一個檔案,並命名為justRunMe
,點兩下...見證奇蹟的Magic出現了
小結
pyinstaller
對於python開發者是個方便打包的軟體,這幾個指令足夠應付一般的使用。- 不過,在windows及Linux(Ubuntu18.04)有個小地方要注意:
1. 跨平台的問題:
Windows:
- 打包的東西能夠順利的拷貝到其他的Windows平台上執行,完全沒問題。
Linux(於Ubuntu18.04測試):
- 如果你打包的系統是
python3.6
,但運行於python3.5或以下版本
的電腦,系統將無法順利運行,原因如下,簡單來說 GLIBC可以往後兼容,但不能往前,所以使用上要注意
2. 編譯後的檔案大小
- 這篇提到,不同的python版本,編譯出來的檔案大小也會不同。
- 根據我的測試,不同的pyInstaller版本,打包的結果也會有所不同,推測應該是掃描相依lib時有所不同
- 我實際測試的結果:
- pyInstaller 3.4 => 打包後60幾mb
- pyInstaller>=3.5 => 打包後120幾mb :