part17:Python打包和釋出(zipapp,PyInstaller)
知識點:
- 釋出 Python 程式
- 使用 zipapp 生成可執行的 Python 檔案包
- 使用 zipapp 建立獨立應用
- 安裝 PyInstaller 模組
- 使用 PyInstaller 生成 EXE 程式
經過一系列的開發、除錯後得到的 Python 程式,接下來就是將這個程式釋出出來。
兩個常用的釋出工具:zipapp 和 PyInstaller。
zipapp 模組生成可執行的 Python 檔案包,該檔案包包含目錄下所有的 Python 程式。如果使用 pip 工具先將 Python 程式所依賴的模組下載到目錄下,那麼就可以生成可獨立遠行的 Python 程式,只要目示機器上安裝有 Python 直譯器環境即可。
PyInstaller 工具更強大,可以直接將 Python 程式編譯成 Windows、Mac OS X 平臺上的可執行程式,而無須這些機器上安裝 Python 環境。
一、使用 zipapp 模組
zipapp 模組可以將一個 Python 模組(可能包含很多個源程式)打包生成一個 Python 應用,或者釋出成一個 Windows 的可執行程式。
1、生成可執行的 Python 檔案包
zipapp 是一個可以直接執行的模組,該模組用於將單個 Python 檔案或整個目錄下的所有檔案打包成可執行的檔案包。命令列語法如下:
python -m zipapp source [options]
source 引數是要打包的 Python 源程式或目錄。如果source引數是目錄,則 zipapp 模組會打包該資料夾中的所有 Python 檔案。options 引數提供的選項如下:
-o <output>, --output=<output>
:指定輸出檔案包的檔名,如果不指定,則使用預設檔名,預設是 source 引數值加上 .pyz 字尾。-p<interpreter>, --python=<interpreter>
:指定 Python 直譯器-m <mainfn>, --main=<mainfn>
:指定入口函式。該選項為 pkg.mod:fn 形式,其中 pkg.mod 是一個檔案包中的包或模組,fn 是指定模組中的函式。如果不指定該選項,則預設從模組中的__main__.py
-c, --compress
:從 Python 3.7 開始支援該選項,指定檔案包進行壓縮來減小檔案的大小,預設是不壓縮。--info
:在診斷時顯示檔案包中的直譯器。-h, --help
:顯示 zipapp 模組的幫助資訊。
zipapp 使用示例:建立一個 app 子目錄,該子目錄下可以有多個 Python 原始檔,在該目錄下的第一個原始檔是 say_hello.py,程式碼如下:
def say_hello(name):
return name + ",您好!"
第二個原始檔是:app.py,用來使用 say_hello 模組,程式碼如下:
from sys import argv
from say_hello import *
def main():
print('開始執行程式')
for arg in argv[1:]:
print(say_hello(arg))
回到 app 子目錄的上一級目錄,在命令列下執行下面的命令:
python -m zipapp app -o first.pyz -m "app:main"
執行上面命令後,app 子目錄下的所有 Python 原始檔都會打包成一個檔案包,-o 選項指定的就是檔案包的檔名;-m 選項指定使用 app.py 模組中的 main 函式作為程式入口。此時在當前目錄會生成一個 first.pyz 檔案,可使用 Python 命令來執行該檔案。示例如下:
> python first.pyz michael tom
開始執行程式
michael,您好!
tom,您好!
在執行打包命令時,如果不指定 -o 引數,則預設輸出的檔名是 source 引數值加上 .pyz字尾組成,例如:
python -m zipapp app -m "app:main"
此時會在當前目錄下生成 app.pyz 檔案。
2、建立獨立應用
為了建立能夠獨立啟動的應用(自帶依賴模組和包),需要執行兩步操作:
第1步:將應用依賴的模組和包下載到應用目錄中。
第2步:使用 zipapp 將應用和依賴模組一起打包成檔案包。
使用 zipapp 建立獨立應用示例:建立 dbapp 子目錄作為本應用的目錄,該目錄下的第一個 Python 原始檔是 exec_select.py 檔案,該原始檔程式碼如下:
import mysql.connector
# 將執行程式碼封裝到 query_db 函式中
def query_db():
# 第1步:連線 MySQL 資料庫,需要提供伺服器IP地址、資料庫埠號、資料庫使用者名稱和密碼,以及資料庫名稱
conn = mysql.connector.connect(user='michael', password='michael123', host='192.168.64.50',
port='3508', database='python', use_unicode=True)
conn.autocommit = True
# 第2步:獲取遊標
c = conn.cursor()
# 第3步:呼叫遊標的 execute() 方法執行 select 查詢語句
c.execute('select * from user_tb where user_id > %s', (4,))
# 通過遊標的 description 屬性獲取列欄位資訊
for col in (c.description):
print(col[0], end='\t')
print('\n-------------------------------')
# 直接使用 for 迴圈遍歷遊標中的結果集
for row in c:
print(row)
print(row[1] + '-->' + row[2])
# 第4步:關閉遊標
c.close()
# 第5步:關閉連線
conn.close()
exec_select.py 檔案的程式碼主要是查詢 MySQL 資料庫中的資料,將主要的執行程式碼都封裝到 query_db() 函式中。
在 dbapp 目錄下的第二個 Python 原始檔是 __main__.py
,這個檔案作為程式入口,這樣在打包檔案時就不需要指定程式入口。該檔案的程式碼如下:
from exec_select import *
# 執行 query_db() 函式
query_db()
接下來按照下面3步將 dbapp 子目錄下的應用打包成獨立應用:
第1步:通過命令列工具在 dbapp 所在的目錄執行下面命令:
python -m pip install -r requirements.txt --target dbapp
上面的命令就是在使用 pip 模組來安裝模組,平時使用 pip 安裝模組提示 pip 錯誤時,也可以使用 python -m pip install
來安裝模組。--target
選項是將模組安裝到指定目錄下,這裡指定的是 dbapp 子目錄下。-r
選項指定要安裝哪些模組,這裡使用 requirements.txt 檔案列出要安裝的模組和包。
-r
選項後面可以直接指定要安裝的模組和包,也可使用清單檔案指定要安裝的模組和包。
如果應用依賴的模組較多,建議使用清單檔案來列出所依賴的模組。為了執行上面的命令,需要提前在當前目錄下準備好 requirements.txt 檔案,該檔案中的內容就一行:
mysql-connector-python
這個 requirements.txt 檔案的每一行代表一個模組,如果有多個依賴模組,就在這個檔案中新增多個模組名的行。執行上面的命令,就開始安裝 mysql-connection-python 模組。完成後可以在 dbapp 子目錄下看到大量有關 mysql-connection-python 模組的檔案。
第2步:如果 pip 在 dbapp 子目錄下生成了 .dist-info 目錄,可以刪除該目錄。
第3步:使用 zipapp 模組執行打包操作,這次有了 __main__.py
檔案,該檔案會作為程式入口,因此在打包時不需要指定 -m 選項。打包命令如下:
python -m zipapp dbapp
此時會在當前目錄得到一個 dbapp.pyz 的檔案包,該檔案包約 20MB,因其包含了 myql-connector-python 模組。
現在,只要目標機器上有合適的 Python 直譯器,即可執行該獨立應用。可先將本機上的 myql-connector-python 解除安裝進行測試。解除安裝命令是:
pip uninstall myql-connector-python
二、使用 PyInstaller 生成可執行程式
1、安裝 PyInstaller
PyInstaller 模組需要自行安裝,安裝命令如下:
pip install pyinstaller
由於該模組還依賴其他模組,所以儘量不要採用離線包方式安裝。若成功安裝,可以在安裝介面看到類似下面的資訊:
Successfully installed pyinstaller-3.6
其中的 3.6 之類的數字,代表 PyInstaller 的版本號。此時,在Python 安裝目錄下的 Script 目錄下也會增加一個 pyinstaller.exe 程式。使用該工具可將 Python 程式生成 EXE 程式。
2、生成可執行程式
PyInstaller 工具的命令語法如下:
pyinstaller 選項 Python原始檔
不管這個 Python 應用是單檔案的應用,壓是多檔案的應用, 只要在使用 pyinstaller 命令時編譯作為程式入口的Python 程式即可。
為了進行示例,先將前面的 app.py 檔案略做修改,將該檔案改成可執行的 Python 程式。程式碼如下:
from sys import argv
from say_hello import *
def main():
print('開始執行程式')
if len(argv[1:]) >= 1:
for arg in argv[1:]:
print(say_hello(arg))
else:
print(say_hello('michael'))
# 增加呼叫 main() 函式
if __name__ == '__main__':
main()
接下來使用命令列工具進入到 app 目錄下,在該目錄下執行下面命令:
pyinstaller -F app.py
執行上面命令,可以看到詳細的生成過程。生成完成後,在app目錄下有一個 dist 目錄,在該目錄下有一個 app.exe 檔案,這就是用 PyInstaller 工具生成的 EXE 程式。
在命令列視窗中進入到 dist 目錄,即可執行 app.exe 程式,示例如下:
...app\dist> .\app.exe tom jack
開始執行程式
tom,您好!
jack,您好!
需要注意的是,這個程式沒有圖形介面,如果雙擊 app.exe 來執行程式,會看到視窗一閃就消失,這樣也看不到程式輸出結果。
另外,pyinstaller 的 -F 選項是指定生成單獨的 EXE 檔案,生成的檔案在 dist 目錄下。在 Mac OS X 平臺上生成的檔案不帶 .exe 字尾。與 -F 選項對應的是 -D 選項(預設選項),該選項指定生成一個目錄(包含多個檔案)來作為程式。
下面使用 -D 選項進行示例。先將 PyInstaller 工具在 app 目錄下生成的 build、dist 目錄刪除,將 app.spec 檔案刪除。然後在app目錄使用下面命令生成 EXE 檔案:
pyinstaller -D app.py
執行這個命令,同樣可以看到詳細的生成過程。生成完成後,在當前目錄下多出一個 dist 目錄,在 dist 目錄下有一個 app 子目錄,在該子目錄下包含了大量的 .dll 檔案和 .pyz 檔案,這些都是 app.exe 程式的支撐檔案。在命令列視窗中執行 app.exe 程式,同樣可以正常輸出。
PyInstaller 不僅支援 -F、-D 選項,還支援其他選項,支援的常用選項如下表所示:
選項 | 作用 |
---|---|
-h, --help | 檢視該模組的幫助資訊 |
-F, --onefile | 產生單個的可執行檔案 |
-D, --onedir | 產生一個目錄(包含多個檔案)作為可執行程式 |
-a, --ascii | 不包含 Unicode 字符集支援 |
-d, --debug | 產生 debug 版本的可執行檔案 |
-w, --windowed, --noconsole | 指定程式執行時不顯示命令列視窗(僅對 windows 有效) |
-c, --nowindowed, --console | 指定使用命令列視窗執行程式(僅對 windows 有效) |
-o DIR, --out=DIR | 指定 spec 檔案的生成目錄。如果沒有指定,則預設使用當前目錄來生成 spec 檔案 |
-p DIR, --path=DIR | 設定 Python 匯入模組的路徑(和設定PYTHONPATH環境變數的作用相似),也可使用路徑分隔符(Windows用分號,Linux用冒號)來分隔多個路徑 |
-n NAME, --name=NAME | 指定專案(產生的spec)名字。如果省略,那麼第一個指令碼的主檔名將作為 spec 的名字 |
PyInstaller 的選項不止上表這些,可以使用 -h 選項檢視 PyInstaller 選項的詳細資訊。
下面使用 PyInstaller 建立一個帶圖形使用者介面,可以訪問 MySQL 資料庫的應用程式。為此,新建一個 dbapp 目錄,將前面建立的 exec_select.py 檔案和 __main__.py
拷貝到新建的 dbapp 目錄,在該目錄下執行下面的命令:
pyinstaller -F -w __main__.py
上面命令中,-F 選項生成單個可執行檔案,-w 選項指定生成圖形使用者介面程式。現在在 dist 子目錄下找到 __main__.exe
檔案,雙擊該檔案即可執行該程式。
小結:
- Python 的兩種打包工具:zipapp 和 PyInstaller。
- zipapp 將檔案打包成一個 .pyz 檔案,該檔案需要 Python 環境來執行。
- PyInstaller 直接打包成可執行程式,該工具還是跨平臺,使用也很方便。使用該工具打包的程式,可以分發到對應平臺的目標機器上直接執行,無須在目標機器上安裝 Python 直譯器環境。