在使用 PyInstaller 打包时,Hook(钩子)文件主要用于告诉 PyInstaller 如何处理那些它无法自动发现的隐藏导入(hidden imports)、数据文件或二进制文件。
添加附加 hook 文件主要有以下三种方式,取决于你的使用场景:
1. 使用命令行参数 --additional-hooks-dir
这是最简单、最直接的方法。如果你有一组自定义的 hook 文件存放在某个文件夹中,可以在打包命令中直接指定该路径。
- 操作: 将你的自定义 hook 文件命名为
hook-<module_name>.py(例如hook-pandas.py)。 - 命令:
pyinstaller --additional-hooks-dir=./my_hooks my_script.py
2. 在 .spec 文件中配置
如果你已经有了 .spec 文件,或者需要更持久的配置,可以直接修改该文件。
- 找到
Analysis对象: 在.spec文件中,找到hookspath参数。 - 修改代码: 将你的文件夹路径添加到列表中。
# my_script.spec
a = Analysis(
['my_script.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=['./my_hooks'], # 在这里添加自定义 hook 文件夹路径
hooksconfig={},
runtime_hooks=[],
# ... 其他配置
)
- 运行打包:
pyinstaller my_script.spec
3. 利用 Entry Points (针对插件/库开发者)
如果你正在开发一个 Python 包,并希望其他人在打包你的包时能自动触发 hook,你可以在项目的 setup.py 或 pyproject.toml 中配置 pyinstaller40.hooks 入口点。这样用户无需手动指定路径,PyInstaller 就能自动识别。
💡 编写 Hook 文件的注意事项
一个标准的 hook 文件通常包含以下内容:
- hiddenimports: 显式告诉 PyInstaller 某些动态导入的模块。
- datas: 包含非代码文件(如 JSON, 配置文件)。
- binaries: 包含动态链接库(.dll, .so)。
示例代码 (hook-capstone.py):
import os
import capstone
capstone_dir = os.path.dirname(capstone.__file__)
dll_path = os.path.join(capstone_dir, "lib", "capstone.dll")
print("HOOK capstone: dll =", dll_path, "exists:", os.path.exists(dll_path))
binaries = [(dll_path, "capstone/lib")]
示例代码 (hook-mysimplenote.py):
from PyInstaller.utils.hooks import collect_data_files
# 自动收集该模块下的所有数据文件
datas = collect_data_files('mysimplenote')
# 手动指定隐藏导入
hiddenimports = ['scipy.special.cython_special']
总结建议
- 临时调试: 用命令行参数
--additional-hooks-dir。 - 项目固定: 修改
.spec文件中的hookspath。 - 确保命名: 文件名必须严格遵循
hook-<模块名>.py的格式,否则 PyInstaller 不会加载它。