在python工程完成开发以后需要编译成可执行文件,如此一来生产环境和开发环境隔离开来便于用户使用(可独立使用,无需配置python开发环境),pyinstaller可以方便地将脚本编译成exe
pip install pyinstaller
pyinstaller xxx.py
一般搞法(多文件)
pyi-makespec xxx.py
pyinstaller xxx.spec
F 生成一个单一可执行文件【常用】
w 禁止弹出控制台【常用】
i 修改exe生成的图标【常用】
h 打印帮助信息
v 打印版本信息
d 生成带各种依赖的文件夹,包含exe,dll,以及其他文件
p 指定搜索路径
Analysis: ['Console.py','xxx.py'...] <- 此处列出的脚本生成exe后会按顺序依次执行! pathex <- 此处为搜索路径 binaries <- 非python的库文件 datas <- ini文件,字体,图片,icon什么的 pure <- python模块 PYZ: <- 不用管 EXE: <- 输出配置 COLLECT: <- 不用管
在生成的spec文件中修改datas字段,形如:
运行命令: pyinstaller xxx.spec --upx [输出路径]
方法1 —— 虚拟环境下打包
造成打包文件太大的主要原因是打包了太多不必要的库,比如安装了anaconda。或者自己pip install了太多库。显然要想解决该问题核心就是不要打包那么多的库。
最好的办法是:在一个虚拟环境中单独打包,只打包该程序执行所必备的依赖库
具体操作方法是:
pip install pipenv
pipenv shell
python xxx.py
pip install pyinstaller ,pyinstaller -Fw xxx.py
exit
关于pipenv更详细使用请参阅
方法2 —— 排除不相干的包
在*.spec的excludes栏目中添加对应的, 常见: excludes=['matplotlib', 'pandas', 'scipy']
,
也可以通过命令行排除: pyinstaller.exe --exclude xxx_package yyy.py
4.2 明明python xxx.py能正常使用, 而打包成exe却无法使用了
主要有以下几种现象:
目前所知主要是两个方面的原因:
python脚本执行的默认路径和exe打包后的路径是不一样的,如果软件中存在文件读取等操作,很有可能导致exe找不到资源而运行出错。
解决该问题的方法是路径冻结
#frozen_dir.py import os,sys def app_path(): if hasattr(sys, 'frozen'): return os.path.dirname(sys.executable) return os.path.dirname(__file__)
添加frozen_dir.py后,app_path会生成一个绝对准确的基地址,所有的路径以此为基准,如下所示:
import frozen_dir SETUP_DIR = frozen_dir.app_path()
依赖包的问题往往出现在:在一开始就pyinstaller打包过程序,后续开发时又安装了新模块,如此一来python xxx.py可以正常执行脚本,但是运行xxx.exe报错。
错误根源可能是:pyinstaller是不会更新__pycache__文件夹的,所以后面增加的模块它不知道,也不会打包进去的:
解决方法非常简单:把打包中生成的资源全部删除【__ pycache __, build, dist】,然后重新打包即可
解决方法1:精简代码,删除不必要的内容
解决方法2: 用-D -w 打包,缺点是文件太多
pyinstaller -D -w -i icon.ico XX.py
FAQ A: -F打包成的exe可以用,带上-w参数去掉console框就不能用了
Q:暂未解决(跟源码中需要获取cmd执行输出有关)
A:-i增加自定义icon功能后,目录下不含icon资源exe执行异常
Q:暂未解决
A: No module named pkg_resources
Q: 有可能是setuptools版本太高所致(请参考文末扩展知识),pip install setuptools==44.0.0
即可
A:failed to execute pyi_rth_pkgres
Q: 有可能是pyinstaller的版本问题,卸载重新安装一下,参考:
我通过降低setuptools版本到 44.0.0 后成功解决问题。
pip install setuptools==44.0.0