使用PyInstaller打包Python PyQt5程序
使用pyinstaller 打包python + pyqt5程序
攻略:
一、打包环境
原则就是在你的项目路径下执行以下所有操作,然后就是如果你用的anaconda,就在该路径下激活你的虚拟环境:conda activate [环境名]
二、执行命令
首先你需要安装pyinstaller。如果你是conda环境,使用conda命令安装:conda install pyinstaller或者 python pip install pyinstaller。 如果普通python环境就是pip install pyinstaller。
我这里是5.11版本,据说4版本有bug,6版本不太一样,没空研究。
然后,进行打包操作。
确定你的程序入口文件(一般是main.py,里面一定有一行代码是 if name == ‘main’:)
确定该文件后,就可以在你的项目目录下执行打包命令了:
pyinstaller -D -w [程序入口文件名].py
这个命令会把相关的所有.py文件都打包成一个exe文件,同时会把环境需要的包都弄过来。
命令解释:
1,-D 表示打包为多文件,区别-F 打包为一个文件,注意:这里一定要选-D,因为-F打包程序不会变小,同时会出一些问题,你运行exe的时候它把你的资源文件复制到C盘某个临时文件夹里,你要改程序去找到它们,有风险还麻烦!
2,-w表示打包为窗口程序,你不加就会有一个控制台黑窗口出现,程序运行的信息会显示在那,如果你调试好了不需要了就使用-w,黑窗口就没了。
3,如果你打包出来的程序名不想用程序入口文件的名字, 可以使用 -n 改名
4,如果你还有其他的python文件,可以使用 -p D:\xxx\xxx.py -p D:\xx2\xx2.py 都加进来,一般用不到,你有无法自动访问的资源文件路径就可以加进来。
5,把你的资源文件(图片、pyqt5的ui文件等)和文件夹都扔进生成好的 【dist/[程序入口文件名]/ xxx.exe】这里,和xxx.exe同一层就行,注意目录结构和原来保持不变,把生成的xxx.exe想象成原来所有的xxx.py文件的集合体,它找资源文件能找到就行。
6, –hidden-import 参数用于指定那些 PyInstaller 无法自动检测到的依赖模块。这些模块虽然在代码中没有直接被 import,但是程序运行时仍然需要它们。
7,–add-data 相当于复制和粘贴,针对一些资源文件、配置文件,你可以用这个命令带过去,两个参数【原文件路径;打包完了目标文件路径】
三、错误处理
3.1 缺少包(搬来的)
打包后运行生成目录dist/main下的exe文件时,出现以下提示:
Invalid async_mode specified
很多答案告诉在生成的spec文件中的hiddenimports中添加一些包,但是尝试了他们的答案,还是没用(治标不治本,每个人缺的包都不一样),于是自己来排查问题。
在pycharm中双击shift找到这个段报错的代码所在的位置,我遇到这个问题是的目录在:C:\Users\ling\AppData\Local\Programs\Python\Python38\Lib\site-packages\engineio\server.py(仅供参考)。可以看到是在engineio这个库的server.py文件中报的这个错。找到具体报错的代码段为:
可以看到是在第145行报的这个错,从代码中可以看出报这个错是因为self.async_mode为空,是在第140行给它赋值时出问题了,看起来是他在导包的时候没有找到这个mode,我们把这个出错的包打印出来,在"except ImportError"后插入以下代码查看出错的包是什么。
raise ValueError("Err mode: " + str(mode))
插入后代码示例(仅添加了一行):
再打包后运行exe,发现报错了:
Err mode: gevent
排查到时缺失到这个包,则在生成的spec文件中的hiddenimports中添加这个库,修改hiddenimports如下(每个人缺的包不一样,需按出错代码段哪里找到相应的路径从而找到要的包):
hiddenimports=[‘engineio.async_drivers.gevent’]
再通过spec文件打包,运行,程序可以启动了。
————————————————
原文链接:https://blog.csdn.net/weixin_42663139/article/details/117400581
3.2 缺少包的终极简单处理
其实上面3.1所说,其原理是这样的,我的程序调用了A包(就是写程序的时候写过 import A),没有调用B包,但是A包里面调用过B包,就是A依赖B,但是因为我的程序里没调用,所以pyinstaller扫描不到,那它打包就不带B(这属实有点呆)。怎么办呢,就是在命令里加–hidden-import 参数,告诉它要有这个包。
简单处理方式:
一旦你发现了这种情况,比如(这个黑窗口闪一下就没了,我录屏截的):
这里有一种简单的处理方式,因为它不就是找不到这个包么,我给它扔进去就完了。
看你的项目引用的目录,注意site-packages这个文件夹,
我的conda虚拟环境安装的所有的包都在这个文件夹下,你就在这里面找找,找什么,找你缺的那个包的名字,你肯定是能找到的,找不到你程序连在pycharm里都运行不起来,反正就在这些引用的目录里面的。
好了,找到了直接复制文件夹,扔到你生成的xxx.exe文件同级目录里面(不一定同级吧,保证与exe文件的相对路径)。
再运行,你就不缺这个包了,它和–hidden-import同理,但是,有些情况–hidden-import加了也不好使,这种方法就好使,这里得给自己点个赞。
这里手动添加包的方法确实有点不太优雅,同样这种复制操作也可以用命令完成 [–add-data ’ A FilePath;B FilePath '],其中AFile表示你要复制的文件的路径,可以是绝对路径或者相对路径,BFile表示打包完了放置的文件路径,一般是相对路径了,意思就是把A文件或文件夹经过打包复制到B那里去。例如:–add-data ‘./UI/*;./UI’
3.3 缺少文件
因为打包不会把资源文件打进去,所以要自己放进来,比如日志文件,图片,pyqt5的ui文件等等,放入到生成dist文件夹里的那个你项目名的文件夹里,和xxx.exe同级(不一定同级吧,保证与exe文件的相对路径)。同样,你可以使用add-data参数免除手动复制的痛苦。
3.4 无限重复启动
如果你使用了多进程的包,比如import multiprocessing 这个包,那么windows打包的时候一定要在程序启动的第一行加上这一行代码,否则就是程序无限启动,直到你的系统崩溃
原文链接:https://blog.csdn.net/weixin_42663139/article/details/117400581
四、建议
作者:liuganlg