当你执行 PyInstaller 时,PyInstaller 做的第一件事就是构建一个.spec
文件;该文件存储在--specpath
目录中,默认情况下就是当前目录。spec
文件实际上是可执行的 Python 代码,PyInstaller通过执行spec
文件来构建应用程序。
以该命令为例:
pyinstaller -F myscript.py
PyInstaller 会首先构建一个myscript.spec
文件,它对你传递给pyinstaller
命令的大部分选项进行编码;生成的myscript.spec
文件内容:
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['myscript.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='myscript',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
一般情况下,你无需检查或修改 spec 文件中的内容;
pyi-makespec 用法
你可以使用pyi-makespec
命令来创建 spec 文件;
pyi-makespac [options] name.py [other scripts ...]
创建 spec 文件并根据需求修改后,可以通过将 spec 文件传递给pyinstaller
命令来构建程序;
pyinstaller [options] name.spec
创建 spec 文件时,大多数命令选项都会编码在 spec 文件中,如果在执行pyinstaller
时指定了这些选项,将会被忽略;
从 spec 文件构建程序时,只有以下选项才有效:
--upx-dir
--distpath
--workpath
--noconfirm
--clean
--log-level
SPEC 文件详解
spec 文件主要使用了 4 个类:Analysis
、PYZ
、EXE
、COLLECT
;
Analysis
:分析你的 Python 脚本依赖,识别需要打包的文件。
a = Analysis(
['myscript.py'], # 主脚本,等同于 `pyinstaller myscript.py`
pathex=[], # 相当于 `--paths=DIR`,设置导入模块时搜索的额外路径
binaries=[], # 额外的二进制文件(如 DLL、.so),无对应命令行选项
datas=[], # 额外的数据文件,等同于 `--add-data`
hiddenimports=[], # 隐式导入模块,等同于 `--hidden-import`
hookspath=[], # 自定义 hook 路径,等同于 `--additional-hooks-dir`
hooksconfig={}, # hook 行为配置项,暂无命令行参数对应
runtime_hooks=[], # 程序启动前执行的钩子脚本,等同于 `--runtime-hook`
excludes=[], # 要排除的模块,等同于 `--exclude-module`
noarchive=False, # 等同于 `--noarchive`,是否禁用 .pyz 打包
optimize=0, # Python 优化等级:0=默认,1=`-O`,2=`-OO`,等同于 `--optimize`
)
PYZ
:创建一个基于 zlib 的 PYZ 档案,其中包含字节编译的纯 Python 模块;也就是将依赖的.pyc
字节码文件打包为.pyz
文件。
通常不需要手动更改;如果noarchive=True
,将不会生成.pyz
文件。
pyz = PYZ(a.pure)
EXE
:生成最终的可执行文件
exe = EXE(
pyz, # PYZ 包
a.scripts, # 主脚本封装器
[], # 其他 zip 文件(通常为空)
exclude_binaries=True, # 等同于 --onedir,推迟二进制文件打包
name='myscript', # 生成的可执行文件名,等同于 `--name`
debug=False, # 启用调试信息,等同于 `--debug`
bootloader_ignore_signals=False, # 忽略信号(用于容器化环境)
strip=False, # 是否用 strip 命令减小体积,等同于 `--strip`
upx=True, # 是否用 UPX 压缩,等同于 `--upx-dir` 自动启用
console=True, # 是否显示控制台,等同于 `--console`(CLI)或 `--windowed`(GUI)
disable_windowed_traceback=False, # 是否关闭 GUI 出错弹窗,等同于 `--disable-windowed-traceback`
argv_emulation=False, # 仅用于 macOS,等同于 `--argv-emulation`
target_arch=None, # 架构目标,如 'x86_64',等同于 `--target-arch`
codesign_identity=None, # macOS 用于代码签名
entitlements_file=None, # macOS 安全许可配置文件
)
COLLECT
:在单目录模式下才会使用,将可执行文件和依赖项打包到输出目录
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False, # 是否再对资源文件 strip(减小体积)
upx=True, # 是否对资源使用 UPX
upx_exclude=[], # 不压缩的文件(支持通配符)
name='myscript', # 输出目录名称,等同于 `--name`
)