PyInstaller 打包单文件 exe 注意事项

tech2023-06-17  114

PyInstaller 打包单文件 exe 注意事项


 

PyInstaller 打包单文件 exe 注意事项 0. 官网1. PyInstaller 打包单文件 exe 时遇到的问题2. 找不到 PyQt5.sip 的解决方案3. 找不到窗体小图标的解决方案4. 找不到 ffprobe.exe 的解决方案5. 使用 subprocess.Popen 无法调用外部程序的解决方案

 


0. 官网

官方网站http://www.pyinstaller.org/官方手册https://pyinstaller.readthedocs.io/en/v3.3.1/

1. PyInstaller 打包单文件 exe 时遇到的问题

我写了一个 Python 小脚本,用来统计当前目录及其子目录下所有视频文件个数与时长,其中用到了 subprocess.Popen 调用了外部 exe 文件 ffprobe.exe ,另外使用 PyQt5 创建了一个简单的小窗体,在窗体标题显示程序图标,源码执行效果如下:

然而在用 PyInstaller 打包成单文件 exe 的时候先后遇到了以下四个问题:

找不到 PyQt5.sip找不到窗体小图标找不到 ffprobe.exe脚本正常运行,调用 ffprobe.exe 出错

以下是针对各个问题的解决方案,其中一些问题有多个解决方案,这里仅提供一种,仅供参考。


2. 找不到 PyQt5.sip 的解决方案

这个问题应该是 PyInstaller 没有导入该模块导致的,在源代码中显式导入即可:

from PyQt5 import sip 1

参考网址:https://blog.csdn.net/yueguangmanong/article/details/81139224


3. 找不到窗体小图标的解决方案

找不到窗体小图标的原因是,单文件打包的时候, PyInstaller 改变了资源存储路径,用原来的相对路径引用不到。

所以首先在源代码中加入 resource_path 函数,该函数返回资源的绝对路径:

def resource_path(relative_path): '''返回资源绝对路径。''' if hasattr(sys, '_MEIPASS'): # PyInstaller会创建临时文件夹temp # 并把路径存储在_MEIPASS中 base_path = sys._MEIPASS else: base_path = os.path.abspath('.') return os.path.join(base_path, relative_path)

然后把所有对资源相对路径的引用传入 resource_path 函数即可,比如:self.setWindowIcon(QIcon(resource_path(r'img\电影.png')))

最后一步,在使用 pyinstaller 命令生成 exe 的时候要使用 --add-data 选项加入所有资源文件。 在 Windows 下该选项的格式为 --add-data="源地址;目标地址" ,可多次重复使用。 其他系统的命令格式需要把地址分隔符从分号 ; 改成冒号 : ,详见官方手册。pyinstaller --add-data="img\电影.png;img" --add-data="ffprobe.exe;." -i="img\电影.ico" -Fw movielen.py


4. 找不到 ffprobe.exe 的解决方案

该问题的产生原因,跟找不到窗体小图标是一样的,所以解决方案也一样。 同样注意,最后使用 pyinstaller 命令的时候需要用 --add-data 选项把 ffprobe.exe 添加进去。 另外,还可以通过编写 spec 配置文件来做到这一点,具体使用方法请查阅官方手册。


5. 使用 subprocess.Popen 无法调用外部程序的解决方案

在我的脚本中,通过 subprocess.Popen 来调用了外部可执行文件 ffprobe.exe ,但是打包成单文件 exe 就运行失败。 原因在于,我在打包过程中使用了 -w 选项,即无控制台模式,这时就需要修改源码,显式指定 subprocess.Popen 的 stdin 、 stdout 和 stderr 参数。 源码修改如下:sp = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell = True)

最终使用以下命令,成功打包了单文件 exe (无控制台模式),并且拥有自己的图标,图片资源完美显示,可以封装并调用别的 exe 文件。pyinstaller --add-data="img\电影.png;img" --add-data="ffprobe.exe;." -i="img\电影.ico" -Fw movielen.py

最终效果如下:

参考网址:https://github.com/pyinstaller/pyinstaller/issues/1339

最新回复(0)