网络上相关教程不少,都不很顺利。自己也尝试好几个打包工具,遇到了大大小小的问题。
变换工具对于解决问题无益,反复尝试Pyinstaller,逐个排查,是最快的方法。
我的环境Win10+Python3.6.2+Pyinstaller3.4+PyQT5.9.2
版本兼容问题
网上不少教程说,Pyinstaller不支持PyQT5.11及更新的版本,推荐Pyinstaller3.2.1+PyQT5.8的组合。
在我的环境下尝试Pyinstaller3.4+PyQT5.12,能成功打包,但会出现如下错误:
![065dd562cf877562fd168d568f88d9f2.png](https://i-blog.csdnimg.cn/blog_migrate/ab65c7d38ad8ac1482eb6a16acd96669.jpeg)
经过验证,Pyinstaller3.4+PyQT5.9.2,运行正常。
动态库错误 WARNING: lib not found:
api-ms-win-crt-utility-l1-1-0.dll dependency of D:TEMPpython36libsite-
packagesPyQt5Qtpluginsplatformsqwindows.dll
等一大串错误
网上不少教程说,需要在pyinstaller时指定 paths D:TEMPpython36libsite- packagesPyQt5Qtpluginsbin,以及plugins等等,并非如此。
其实这里主要是api-ms-win-crt-runtime动态库之类的错误,是因为Universal CRT(KB2999226)缺失,可以通过安装此更新来解决问题,或者直接下载 Visual C++ Redistributable。
最简单的解决办法:网络上找到 vc2015dll包,将dll文件放入对应的文件夹(C/windows/system32下)即可,如果使用64位系统,下载的时候需要区分。
loadUi( 'main.ui', self)引起的闪退
打包后的文件
如果在main.py中使用了loadUI方法来加载ui文件,那么打包时需要Pyinstaller --add-data="main.ui;." main.py
不然运行exe的效果就是闪退。
调用ui文件有两种方法:
1)使用PyUIC将.ui文件转换为.py文件,然后from import方法调用。这种方式每次修改UI都要转换一下,比较麻烦
2)直接导入from PyQt5.uic import loadUi,然后在初始函数def __init__(self): 下面使用loadUi('main.ui', self)调用ui文件
其次,根据Run-time Information,程序还要如此修改:
def __init__(self):
super(self).__init__()
if getattr(sys, 'frozen', False):
# we are running in a bundle
bundle_dir = sys._MEIPASS
else:
# we are running in a normal Python environment
bundle_dir = os.path.dirname(os.path.abspath(__file__))
loadUi(bundle_dir + 'main_UI.ui', self)
可以参考:PyQt5学习笔记4_loadUi加载ui文件 - yy123xiang的专栏 - CSDN博客
PyQt5学习笔记4_loadUi加载ui文件 - yy123xiang的专栏 - CSDN博客blog.csdn.net![174320560f9ad758f161452924b19cba.png](https://i-blog.csdnimg.cn/blog_migrate/806aaf9cf3a30ade679fbf2687e1e430.png)
Fail to execute script xx
偶有遇到。从GitHub里的issue看,这里主要往往都是路径问题,仔细检查各文件路径,脚本里的路径,检查环境变量。
排查路径的小经验是:不选择单文件打包,而是动态打包,打包完成的文件夹中,查看调用的各资源文件是否成功被打包。
检查打包生成的spec文件,查看打包设置的文件路径是否正确。
当然也有一种很意外的情况。Qtdesigner生成的.ui文件,会因为某种错误,运行okay,但打包运行会出现fail to execute的错误。崩溃的我,内心在嘶吼“什么都没改啊,就微调了一下界面而已”。最后通过pycharm历史文件功能,恢复了一下.ui文件就正常了。
运行去命令窗
默认情况下,打包的exe运行会有命令窗,GUI程序不需要,打包时--noconsole即可,-w也是一样。
pyinstaller -F --add-data="main.ui;." main.py --noconsole
其他
pyinstaller --debug ALL main.py
pyinstaller -i name.ico main.py
很多教程都比较简洁,直接-d 或者 --debug,在现在的Pyinstaller中,--debug后面需要带参数比如 ALL,可以帮助你查看具体错误,方便troubleshooting。
而-i则可以将同路径下的图标打包进去。
仍然存在的问题
1. 目前发现exe文件在最小图标显示情况下,不能显示打包进去的图标。
2. Pyinstaller打包后的文件太大了,很小的一个程序仍然18mb。使用upx打包后,文件大小降为14mb,但运行会有dll文件相关报错。
3. 打包文件只能适应原环境(win10/64位),想要迁移到其他环境中运行,需要在对应环境下分别打包。
写程序两小时,打包两天,反复卸载重装,被无情嘲讽。