💥打包的 `.exe` 閃退了?別慌!教你逐步排查 PyInstaller 打包的所有錯誤!
- 🛠 運行 `.exe` 查看報錯信息
- ? 正確姿勢:
- ? importlib 動態導入導致打包失敗
- ?什么是動態導入?
- ? 解決方式:
- 📦 包元數據丟失問題:`importlib.metadata.PackageNotFoundError`
- 🎯 根本原因:
- ? 解決方法一:打包命令添加參數
- ? 解決方法二:使用 `.spec` 文件方式
- ? DLL 加載失敗:WinError 127
- ? 修復步驟:
- ? 第一步:找到 torch 的 lib 路徑
- ? 第二步:修改 `.spec` 文件
- 🔧 終極解決方案:用 `PyInstaller.__main__` 寫一個自定義 `package.py`
- ? 優點:
- 🔚 總結
- 🧠 附:打包常見庫建議參數
前面的只是學習,雖然問題解決了,但是一個個問題又冒出來了,可以直接看最后一部分,我換了一個方法。
🛠 運行 .exe
查看報錯信息
很多人在直接雙擊 .exe
文件時,會發現它“一閃而過”就沒了。這是因為程序崩潰了,報錯信息來不及顯示。
? 正確姿勢:
- 打開終端(CMD 或 PowerShell)
- 切換到
.exe
文件所在目錄 - 運行:
cd dist\your_program
.\your_program.exe
如圖所示:
? importlib 動態導入導致打包失敗
?什么是動態導入?
很多庫使用 importlib.import_module("模塊名")
來動態加載模塊,而不是傳統的 import 模塊名
。
PyInstaller 只能分析靜態導入,遇到動態導入時,它就不知該打包啥了,運行就會提示模塊缺失或功能失效。
? 解決方式:
在 spec
文件的 datas
中手動添加:
datas = [(r"G:\anaconda\envs\pcb\Lib\site-packages\ultralytics", "ultralytics"),
]
重新打包即可。
📦 包元數據丟失問題:importlib.metadata.PackageNotFoundError
報錯信息:
importlib.metadata.PackageNotFoundError: No package metadata was found for torchvision
🎯 根本原因:
PyInstaller 默認不會打包 metadata,而有些庫(如 ultralytics
)使用:
importlib.metadata.version("torchvision")
來獲取依賴庫的版本,因此需要明確告訴它:把 metadata 一起帶上!
? 解決方法一:打包命令添加參數
pyinstaller --onefile ^--collect-all ultralytics ^--copy-metadata=torch ^--copy-metadata=torchvision ^--copy-metadata=ultralytics ^main_window.py
? 解決方法二:使用 .spec
文件方式
在 .spec
中添加:
from PyInstaller.utils.hooks import copy_metadatadatas += copy_metadata('torch')
datas += copy_metadata('torchvision')
datas += copy_metadata('ultralytics')
? DLL 加載失敗:WinError 127
錯誤提示:
OSError: [WinError 127] 找不到指定模塊
Error loading "torch\lib\caffe2_detectron_ops.dll"
說明 PyInstaller 沒把某些 .dll
一起打包!
? 修復步驟:
? 第一步:找到 torch 的 lib 路徑
運行:
python -c "import torch; print(torch.__path__)"
假設路徑為:
G:\anaconda\envs\pcb\Lib\site-packages\torch
? 第二步:修改 .spec
文件
import glob
import ostorch_dlls = [(f, os.path.join('torch', 'lib')) for f in glob.glob(r'G:\anaconda\envs\pcb\Lib\site-packages\torch\lib\*.dll')
]a = Analysis(['main_window.py'],...binaries=torch_dlls,datas=[(r"G:\anaconda\envs\pcb\Lib\site-packages\ultralytics", "ultralytics"),(r"G:\anaconda\envs\pcb\Lib\site-packages\torch", "torch"),(r"G:\anaconda\envs\pcb\Lib\site-packages\torchvision", "torchvision"),],...
)
🔧 終極解決方案:用 PyInstaller.__main__
寫一個自定義 package.py
上面的方法,始終有問題。耽誤了我一天的時間,最終終于找到了解決的方案。換了一種方法。
import PyInstaller.main
你可以自己寫一個 package.py
腳本統一管理打包邏輯:
import PyInstaller.__main__PyInstaller.__main__.run(['--onefile','--nowindowed','-n', 'defect_detect','-i', 'ui/ui_imgs/icons/目標檢測.ico','--add-data=ui/ui_imgs/icons;ui/ui_imgs/icons','--add-data=view/style.css;view','--copy-metadata=torch','--copy-metadata=torchvision','--copy-metadata=ultralytics','--collect-all', 'ultralytics','main_window.py',
])
? 優點:
- 不再需要手動修改
.spec
- 自動包含 metadata
- 可重復運行,一鍵打包!
🔚 總結
錯誤類型 | 解決方案 |
---|---|
exe 閃退 | 命令行運行查看報錯 |
動態導入庫找不到 | datas手動添加路徑 |
metadata 丟失 | 添加 --copy-metadata 參數 |
DLL 加載失敗 | torch/lib/*.dll 添加進 binaries |
打包太麻煩 | 用 PyInstaller API 腳本自動化 |
🧠 附:打包常見庫建議參數
庫名稱 | 打包建議 |
---|---|
ultralytics | --collect-all ultralytics |
torch | --copy-metadata=torch + 添加 dll |
torchvision | --copy-metadata=torchvision |
numpy | 一般自動打包 |
matplotlib | 建議 --collect-submodules |
如果你覺得本篇文章對你有幫助,歡迎點贊、收藏、轉發!🚀
更多 PyInstaller 技術細節、實戰案例持續更新中~
有任何問題也歡迎評論區留言交流!