pyinstaller 可以用来把 python 打包成可执行二进制文件,但是在打包会遇到很多问题,尤其在 windows 系统上打包 exe 时。
打包编译还可以使用 nuitka。把 python 脚本编译成 C 语言。
nuitka 基本使用
安装语法
pip install nuitka
python -m nuitka xxx.py --standalone --onefile --windows-icon-from-ico=favicon.ico
常用参数
--standalone
# 可运行在没有 python 的环境中
--onefile
# 生成单文件
-windows-icon-from-ico=
# 打包 icon 文件(默认无图标)
其他参数
可使用 python -m nuitka -h
来查看,参数众多,有需要现查看即可。
运行过程
首次运行,会请求下载 gcc 编译相关文件。需要输入 yes 会直接按回车继续。如果下载慢可根据提示手动下载并放到指定的目录下。请求下载的文件有 2 个。再次编译则不再重新下载。
请求下载的文件有 2 个:
- gcc 编译器
Dependency Walker- ccache
再次编译则不再重新下载,若间隔时间过长,则会重新下载最新的版本。由于是从 github.com 下载,可能速度过慢,可手动复制 url 下载到指定目录下,重新运行打包。
打包速度比 pyinstaller 慢得太多。且会将所有下载的 python 包全部打包,为了缩小体积,不得不用pipenv
等虚拟环境。
打包后会生成 3 个文件夹: xxx.build
、xxx.onefile-build
、xxx.dist
。
涉及到二次引用其他包的情况可能会报错,比如使用了 pandas.read_excel()
读取 excel,其实的调用了 openpyxl
,正常不 import openpyxl
可以正常运行,使用 nuitka
打包则提示找不到包。让我不得不用 pyinstaller
。
pyinstaller 基本使用
安装语法
pip install pyinstaller
pyinstaller --clean -F xxx.py -i favicon.ico
pyinstaller --clean -F xxx.spec
常用参数
-D, --onedir
# 输入到文件夹(默认)
-F, --onefile
# 打包到单文件
-c
# windwos 下启动时打开命令行窗口(默认)
-w
# windwos 下启动时无命令行窗口
-i
# 打包 icon 文件(默认和 python.exe 一样)
-n
# 指定输出的文件/文件夹名(默认第一个脚本名)
不常用参数
--add-data <SRC;DEST or SRC:DEST>
--add-binary <SRC;DEST or SRC:DEST>
--version-file
--uac-admin
-r
-m, --manifest
执行pyinstaller -h
查看更多参数。
打包后会生成 *.spec
文件、以及 build
、dist
文件夹。exe 文件在 dist
里。
配置文件
.spec
是打包配置文件,在执行一次打包操作后会生成。如果打包后的 exe 无法运行缺少资源。可以修改它并再次打包。
pyinstaller xxx.spec
正常情况下 pyinstaller 会自动识别需要打包进去的资源,但有时候并不准,复杂的 import 关系识别不到,运行 exe 时会提示包不存在。比如在打包 PyQt 。
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
add_files = [
('./data','data'),
('./imgs','imgs'),
('./setting','setting')
]
a = Analysis(['xxx.py'],
pathex=['D:\\home\\pyqt_test'],
binaries=[],
datas=add_files,
...
)
pyz = PYZ(...)
exe = EXE(pyz,
...
name='xxx',
...
console=False, icon='./dist/favicon.ico')
add_files
是一个列表,列表里元素是元组。 元组第一项是要引用的外部资源的路径(可以是文件/文件夹),第二项是打包进 exe,在 exe 中的路径(所在文件夹)。
设置文件版本信息
为了方便版本管控,最好是给每次打包发布的 exe 文件设置文件版本信息——右键点击 exe 查看属性中的详情信息中可以看到版本信息。
方法一:
进入 pyinstaller 的安装目录:\Lib\site-packages\PyInstaller\utils\cliutils\
,找到
grab_version.py
set_version.py
其中的 grab_version.py
是用来捕获一个 exe
文件的版本信息并自动在同一目录下输出一个 file_version_info.txt
文件版本信息的,其中 set_version.py
是用来给一个 exe
文件赋值版本信息的,用法分别如下:
- 进入 cmd 界面
- 目录转移到 \Lib\site-packages\PyInstaller\utils\cliutils\ 下
- 拷贝一个要获取版本信息的 exe 文件到这个目录下
- 在 cmd 窗口键入:
python grab_version.py filename.exe
- 目录下会自动出现一个标准的 file_version_info.txt 文件,双击打开,按照相应的需求修改
- 在cmd窗口键入:
python set_version.py file_version_info.txt youfilename.exe
即可
方法二:
- 在打包的时候就已经准备好了版本信息文件:file_version_info.txt
- 打包时用此参数
--version-file
即可:pyinstaller --version-file file_version_info.txt xxx.py
最后打包成 exe,可以右键点击 exe 文件查看详细信息,可以看到有文件版本信息。
设置管理员权限执行
如果需要用管理员权限执行,即双击 exe 文件运行时,需要弹出一个 uac 界面让用户授权。怎么做?
首先打包一次:
pyinstaller -F --uac-admin xxx.py
来到``目录,找到*.manifest
文件,把它复制到 py 文件的同级目录下
pyinstaller -F --uac-admin -r xxx.exe.manifest,1 xxx.py
# 或直接执行:
pyinstaller -F --uac-admin -r build/xxx.exe.manifest,1 xxx.py
添加了参数:-r xxx.exe.manifest,1
,打包后的 exe 带小盾牌图标了。双击运行弹出了uac 界面。
报错处理
如果执行打包后的 exe 文件闪退。可在 cmd 下执行,查看报错信息。
使用软件:Dependency Walker,可以自动搜素缺失的组件。可以为分析问题提供些帮助。
参考
手把手教你将pyqt程序打包成exe,https://blog.csdn.net/tb_youth/article/details/105758308
Pyinstaller 打包发布经验总结,https://blog.csdn.net/weixin_42052836/article/details/82315118
pyinstaller 打包 exe(含file version信息),https://www.cnblogs.com/danvy/p/10505731.html
–uac-admin 选项不起作用,https://blog.csdn.net/qq_26373925/article/details/105373124