知識點:
- 發布 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 解釋器環境。