# 基本操作
# 多py文件打包
# pyi-makespec指定的参数被直接添加到spec中
# -F, --onefile Create a one-file bundled executable.
# -w, --windowed, --noconsole # 无控制窗口
# --add-data "\path\web;web" # 把web文件夹打包到dist\app\_internal的web中,使用该参数时建议不使用-F, --onefile指令
# --icon=app.ico # 指定采用的图标
pyi-makespec -F -w app.py # 生成spec文件
pyinstaller app.spec # 利用spec文件打包应用
在多 python 文件开发时,可以在每个模块下面加上 __init__.py
文件,使得 python 将其识别为模块,调用时就用 from . import xx.py
或者 from .xx import xxx
之类的,然后 app.py
文件放置在和模块文件夹的同级的目录下调用该模块,这样打包时,只需把模块文件夹的目录加入 spec 文件中的 pathex 参数中便可以了(相当于一个本地库,直接加入 python 搜索路径了)。某模块文件夹的 tree 指令打印如下:
C:.
│ constants.py
│ __init__.py
│
├─core
│ ssh_service.py
│ websockets_service.py
│ __init__.py
│
├─events
│ events.py
│ __init__.py
│
├─presenters
│ main_presenter.py
│ __init__.py
│
└─views
│ control_view.py
│ docx_dialog_view.py
│ file_view.py
│ html_dialog_view.py
│ image_dialog_view.py
│ log_view.py
│ main_window.py
│ step_view.py
│ terminal_view.py
│ text_dialog_view.py
│ __init__.py
│
└─web
index.html
xterm.css
xterm.js
参考
- PyQt5 单项目单文件 / 多文件架构使用 PyInstaller 打包教程_pyqt5 打包 - CSDN 博客
- Python 程序部署利器:PyInstaller 打包 exe 详解 - OSCHINA - 中文开源技术交流社区
# hook 文件的问题
诸如 failed to execute pyi_rth_pkgres
、 FileNotFoundError: 'Lorem ipsum.txt' resource not found in 'jaraco.text'
等,都是由于钩子文件(hook file,即告诉 PyInstaller 如何正确捆绑包的脚本)的问题,使用下面指令解决该问题:
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
参考
- python 解决 “failed to execute pyi_rth_pkgres” 问题_failed to execute script pyi rth pkgres-CSDN 博客
- python - Pyinstaller "Failed to execute script pyi_rth_pkgres" and missing packages - Stack Overflow
- python - Pyinstaller: FileNotFoundError: 'Lorem ipsum.txt' resource not found in 'jaraco.text' - Stack Overflow
# 程序访问文件夹
为了使得在打包为 exe 文件后,程序仍可正确找到路径,可以用如下代码,其中 sys._MEIPASS 代表 dist\app\_internal 文件;
注意此时不宜使用 - F, --onefile 参数,不然会没有该文件
html_path = resource_path(os.path.join("web", "index.html"))
def resource_path(relative_path):
"""获取打包后资源文件的绝对路径"""
if hasattr(sys, '_MEIPASS'):
# 如果是打包后的环境
base_path = sys._MEIPASS
# 获取exe文件所在的目录
# if getattr(sys, 'frozen', False):
# # 打包后的环境
# return relative_path # 直接返回相对路径
# if getattr(sys, 'frozen', False):
# # 打包后的环境
# base_path = os.path.dirname(sys.executable)
else:
# 开发环境,直接使用当前路径
# base_path = os.path.abspath(".")
base_path = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base_path, relative_path)
参考
- (97 封私信 / 30 条消息) 使用 PyInstaller 打包 Python 项目(多文件、图标、附件支持)—— 详尽指南 - 知乎
- python pyinstaller 打包携带文件夹_mob649e815c3b9e 的技术博客_51CTO 博客
# QWebEngineView 的问题
现象:在代码中 self.web_view = QWebEngineView()
创建 Web 视图,用 pyinstaller 打包为 exe 文件后,点开后会立即闪退。
原因:pyinstaller 从 pyqt5 中拷贝的库不全
解决:可以手动拷贝过去,例如用 conda 创建的虚拟环境 myUi,其 pyqt5 下的 qt5 库路径为 \path\anaconda3\envs\myUi\Lib\site-packages\PyQt5\Qt5,把 bin、plugins、qml、resources、translations 文件都拷贝到打包后 \path\dist\app_internal\PyQt5\Qt5 文件夹中进行替换就行了。
最终:不过经过排查,我所遇到的问题,只需用 \path\anaconda3\envs\myUi\Lib\site-packages\PyQt5\Qt5\bin\QtWebEngineProcess.exe 把 \path\dist\app_internal\PyQt5\Qt5\QtWebEngineProcess.exe 替换掉就能解决问题了。
参考
# 程序图标设置
在线把图片转为.ico 格式,放在打包目录下使用 --icon=app.ico 添加即可
这样仅是把桌面图标设置为了该图片,为了使得弹窗中左上角的小图标也设置为该图片,可使用 app.setWindowIcon(QIcon('app.ico'))
,简单一点的话,直接把 ico 图片放置在打包后的 exe 同目录下就行了
如果设置后桌面图标没有刷新,重启一下电脑就好了
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon('app.ico'))
win = IconSet()
win.show()
sys.exit(app.exec_())
参考
- 如何设置 pyQT5 程序图标 - zi's blog
- PyQt5 - 如何设置应用和窗口的图标?控件的提示信息如何设置?- 腾讯云开发者社区 - 腾讯云
- Pyinstaller 打包后,EXE 在系统桌面不显示自定义图标? - 知乎
# 零散的
# spec 文件结构
# 体积缩减
# Nuitka
Python 打包工具 Nuitka 入门指南 - CSDN 博客