reference_packaging.md 2.58 KB
name: PyInstaller 打包配置 (task #19)
description: ZB100ImageGenerator.spec 当前形状 + 易踩坑(QML 路径 / Pillow / pathex)
type: reference
originSessionId: 21abab40-0d6c-449a-ae72-9ca03205f077

spec 当前形状(2026-05-10)

a = Analysis(
    ['qml_poc/main_qml.py'],          # 入口(不是老 image_generator.py)
    pathex=[str(Path('.').resolve())], # 项目根,让 PyInstaller 找 audit_logger 等顶层模块
    binaries=pil_native_libs,          # Pillow .dylibs/.libs collect_dynamic_libs
    datas=[
        ('config.json', '.'),
        ('qml_poc/qml', 'qml'),         # ← 目标路径不带 qml_poc/ 前缀!
        ('jewelry_library.json', '.'),
    ] + 平台特定:
        IS_WIN: ('zb100_windows.ico', '.')
        IS_MAC: ('zb100_mac.icns', '.')
    hiddenimports=[
        'PySide6.QtQml', 'PySide6.QtQuick', 'PySide6.QtQuickControls2',
    ],
)

关键坑(踩过的)

  1. QML datas 目标路径必须是 qml/ 不是 qml_poc/qml/ 原因:PyInstaller 把入口脚本 qml_poc/main_qml.py 平铺到 _MEIPASS/main_qml.py (不是 _MEIPASS/qml_poc/main_qml.py),所以 Path(__file__).parent / "qml" = _MEIPASS/qml。datas 写 ('qml_poc/qml', 'qml') 才对得上。

  2. pathex 必须显式给项目根 main_qml.py 顶部 sys.path.insert(0, ROOT) PyInstaller 静态分析看不到, 不给 pathex → 打包后 from audit_logger import ... ModuleNotFoundError。

  3. Pillow .dylibs 在 macOS 上必须收集 spec 里有完整逻辑(collect_dynamic_libs + 显式枚举),输出量在 console。 macOS 验证打包要看 [spec] 最终 Pillow 原生库数量: > 0

构建命令

  • Windows: build_windows.bat.venv/Scripts/pyinstaller.exe ZB100ImageGenerator.spec --noconfirm
  • macOS: bash build_mac_universal.sh (顺便打 .dmg,含 drag-to-install 布局)

产物路径

  • Windows: dist/ZB100ImageGenerator/ZB100ImageGenerator.exe + _internal/
  • macOS: dist/ZB100ImageGenerator.app + dist/ZB100ImageGenerator.dmg

Windows 验证状态(2026-05-10): 打包通过 → 启动 8 phases 全过 → QML 装载成功 → 进入主循环零警告。 日志在 dist/ZB100ImageGenerator/logs/app.log

macOS 验证状态:未做(开发机是 Windows)。明早起来 bash build_mac_universal.sh 跑一遍验证,重点看 .dmg 在 NAS / 邮件传输后 PIL/.dylibs symlink 是否完整。

仍未删的旧入口image_generator.py.txt(2026-05-10 git mv 改 .txt,不参与打包扫描) 用户要求确认 QML 版稳定后再删。