PyInstaller打包Python詳解
一、PyInstaller簡介
1.PyInstaller可以將Python項目在不同平台上打包為可執行文件.
2.PyInstaller打包的流程:讀取編寫好的Python項目-->分析其中條用的模塊和庫,並收集其文件副本(包括Python的解釋器)-->將副本和Python項目文件(放在一個文件夾//封裝在一個可執行文件)中.
二、pyinstaller的參數列表
參數 | 參數意義 |
---|---|
-F --onefile |
1.打包單個文件,產生一個文件用於部署(默認),如果代碼都寫在一個.py文件時使用,項目有多個文件時不要使用 例:pyinstaller -F xxx.py 例:pyinstaller --onefile xxxx.py |
-D --onedir |
1.打包多個文件,產生一個目錄用於部署(默認),用於框架編寫的代碼打包 例:pyinstaller -D xxx.py(項目入口文件) 例:pyinstaller --onedir xxx.py(項目入口文件) |
--key=keys | 1.使用keys進行加密打包 例:pyinstaller --key=1234 -F xx.py |
-K --tk |
1.在部署時包含 TCL/TK |
-a --ascii |
1.不包含編碼.在支持Unicode的python版本上默認包含所有的編碼 |
-d --debug |
1.產生debug版本的可執行文件 |
-n name --name=name |
1.可選的項目(產生的spec的)名字name 2.第一個腳本的主文件名將作為spec的名字(默認) 例:pyinstaller -F -n my_file_name xxx.py 例:pyinstaller -F --name=my_file_name xxx.py |
-o dir -- out=dir |
1.指定spec文件的生成目錄dir 2.如果沒有指定且當前目錄是PyInstaller的根目錄,會自動創建一個用於輸出(spec和生成的可執行文件)的目錄 3.如果沒有指定切當前目錄不是PyInstaller的根目錄,則會輸出到當前的目錄下 |
-p dir --path=dir |
1.用來添加程序所用到的包的所在位置,設置導入路徑(和使用pythonpath效果相似) 2.可以用路徑分割符(Windows使用分號,Linux使用冒號)分割,指定多個目錄.也可以使用多個-p參數來設置多個導入路徑,讓Pyintaller自己去找程序需要的資源 |
-w --windowed --noconsole |
1.表示去掉控制台窗口,使用Windows子系統執行,當程序啟動的時候不會打開命令行(只對Windows有效) 例:pyinstaller -c xxx.py 例:pyinstaller xxx.py --noconsole |
-c --nowindowed --console |
1.表示打開控制台窗口,使用控制台子系統執行,當程序啟動的時候會打開命令行(默認)(只對Windows有效) 例:pyinstaller -c xxx.py 例:pyinstaller xxx.py --console |
-i --icon=<file.ioc> |
1.將file.ico添加為可執行文件的資源,改變程序的圖標(只對Windows系統有效) 例:pyinstaller -F -i file.ico xxx.py 例:pyinstall -F --icon=<file.ioc> xxx.py |
--icon=<file.exe,n> | 1.將file.exe的第n個圖標添加為可執行文件的資源(只對Windows系統有效) |
-v file --version=file |
1.將verfile作為可執行文件的版本資源(只對Windows系統有效) |
-s --strip |
1.可執行文件和共享庫將run through strip.注意Cygwin的strip往往使普通的win32 Dll無法使用 |
-X --upx |
1.如果有UPX安裝(執行Configure.py時檢測),會壓縮執行文件(Windows系統中的DLL也會)(參見note) |
三、Pyinstaller的使用
- PyInstaller在Windows/Linux/Mac環境下的使用:執行命令相同,只需要在不同環境下執行即可
1.pyinstaller的安裝
pip install pyinstaller
2.執行命令
- 2.1打包單個文件
# 1.執行命令
pyinstaller -F xxx.py
# 2.去生成的dist文件夾找xxx.exe運行
# 3.運行成功,xxx.exe則為可執行文件,刪除其它文件
- 2.2打包多個文件
# 1.執行命令,xxx.py為程序入口文件
pyinstall -D xxx.py
# 2.刪除生成的bulid和dist文件夾,僅保留xxx.spec文件
# 3.修改xxx.spec文件,詳見2.2.1
# 4.執行命令
pyinstaller -F xxx.spec
# 5.去dist文件夾下找xxx.exe文件
# 6.運行成功,刪除臨時文件目錄build;dist目錄為打包的結果,可執行文件和其它程序運行的關聯文件都在這個目錄下
- 2.2.1 xxx.spec配置文件詳解
# -*- mode: python -*-
block_cipher = None
# 以py文件為輸入,分析py文件的依賴模塊,並生成相應的信息
a = Analysis(['xxx.py'], # 要打包.py文件名列表,和xxx.py同級可以不同添加
pathex=['D:\\abc\\def\\project_v1.0'], # 項目路徑
binaries=[], # 程序調用外部pyd、dll文件(二進制文件路徑)以數組形式傳入;例:('D:\\pro\\text.dll', 'pro'),將'pdftotext.dll'pro,與原項目結構一致即可
datas=[], # 存放的資源文件(圖片、文本等靜態文件)以數組形成傳入;例:('D:\\static\\c.ioc','static'),將'cc.ioc'打包之后放在static目錄,與原項目結構一致即可
hiddenimports=[], # pyinstaller解析模塊時可能會遺漏某些模塊(not visible to the analysis phase),造成打包后執行程序時出現類似No Module named xxx;這時就需要在hiddenimports中加入遺漏的模塊
hookspath=[],
runtime_hooks=[],
excludes=[], # 去除不必要的模塊import,寫在excludes中添加此模塊
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
# .pyz的壓縮包,包含程序運行需要的所有依賴
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
# 根據Analysis和PYZ生成單個exe程序所需要的屬性及其配置
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='xxx', # 生成exe文件的名字
debug=False, # debug模式
strip=False,
upx=True,
console=False, # 是否在打開exe文件時打開cmd命令框
icon='C:\Users\xx.ico' ) # 設置exe程序圖標,ico格式文件(16*16)
# 收集前三個部分的內容進行整合,生成程序所需要的依賴包,及資源文件和配置
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='fastplot')
四、踩坑
- 編輯.spec文件路徑相關
1.windows盡量使用絕對路徑,用雙斜杠\ \
2.linux路徑/home/my_project/web
3..路徑避免使用中文
- 打包.spec文件報錯:RecursionError: maximum recursion depth exceeded
1.在spec文件上添加遞歸深度的設置
import sys
sys.setrecursionlimit(5000)
- 更換exe圖標報錯:AttributeError: module 'win32ctypes.pywin32.win32api' has no attribute 'error'
1.圖標的大小建議(64*64): https://lvwenhan.com/convertico/
2.圖標的顏色嚴格限制:256,真彩色是不行的
- 打包錯誤:ModuleNotFoundError: No module named 'xxxxx'
方法1:pyinstaller -D --hidden-import="xxxxx" main.py
方法2:在xxx.spec中配置hiddenimports=['xxxxx']
- 運行exe文件報錯:Failed to excute Script main
1.使用-c模式重新打包調試,找的缺失的模塊,pip install安裝
- 文件打包后過大
1.在程序中盡量不使用import xx;而是使用 from xx import xx