使用 PyInstaller 打包多依赖 Python 项目为 EXE

将复杂依赖的 Python 项目转换为独立 EXE 文件,需解决路径处理、隐藏导入、资源打包等问题。以下是具体操作流程和优化方案。


准备项目结构与依赖管理

确保项目目录清晰,依赖库通过 requirements.txt 管理:

pip freeze > requirements.txt

检查是否存在动态导入(如 __import__()importlib),这类依赖需手动声明。


安装 PyInstaller 并生成基础 SPEC 文件

安装最新版 PyInstaller:

pip install pyinstaller --upgrade

生成 SPEC 模板文件(以 main.py 为例):

pyinstaller --name=MyApp --onefile main.py

生成的 MyApp.spec 文件是打包的核心配置文件。


修改 SPEC 文件处理复杂依赖

编辑 SPEC 文件的关键部分:

  1. 添加隐藏导入:在 Analysis 块中补充动态加载的库(如 OpenCV、Pandas):

    hiddenimports=['cv2', 'pandas._libs.tslibs.timedeltas']
    

  2. 包含数据文件:指定静态资源(如图片、配置文件)的路径映射:

    datas=[('assets/*.png', 'assets'), ('config.json', '.')]
    

  3. 排除无关库:减少体积,例如排除测试模块:

    excludes=['unittest', 'pytest']
    

完整示例:

a = Analysis(
    ['main.py'],
    pathex=['/project/path'],
    binaries=[],
    datas=[('assets/*', 'assets')],
    hiddenimports=['sklearn.utils._weight_vector'],
    hookspath=[],
    excludes=['django'],
    ...
)


处理常见依赖问题

场景 1:库未自动打包

  • 使用 --collect-all 强制包含整个包:
    pyinstaller --collect-all tensorflow main.py
    

场景 2:运行时 DLL 丢失

  • 将缺失的 DLL 放入项目目录,并在 SPEC 中声明:
    binaries=[('C:/libs/opencv_world.dll', '.')]
    

场景 3:路径问题导致资源加载失败

  • 在代码中使用 sys._MEIPASS 兼容开发与打包环境:
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(__file__))
    config_path = os.path.join(base_path, 'config.json')
    


构建与调试

通过 SPEC 文件执行打包:

pyinstaller MyApp.spec

调试建议

  • 若 EXE 闪退,通过命令行运行查看报错:
    dist/MyApp.exe
    

  • 使用 --debug=all 生成详细日志:
    pyinstaller --debug=all main.py
    


进阶优化

  1. UPX 压缩:减少体积,需下载 UPX 并配置:

    exe = EXE(
        ...
        upx=True,
        upx_exclude=['vcruntime140.dll']
    )
    

  2. 版本信息:添加图标和元数据(需 .rc 文件或 --version-file)。

  3. 分发包:用 NSISInno Setup 制作安装程序。


验证与分发

在纯净虚拟机中测试 EXE 兼容性,确保无缺失依赖。最终分发时建议包含:

  • 主程序 EXE
  • 必要的 DLL 文件(如 vcruntime140.dll
  • 使用说明文档

通过上述步骤,可将多依赖 Python 项目高效打包为独立 EXE,适用于 Windows 环境分发。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐