PyInstaller打包时如何添加附加 hook

目录

在使用 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.pypyproject.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 不会加载它。