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',
],
)
关键坑(踩过的):
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')才对得上。pathex 必须显式给项目根 main_qml.py 顶部
sys.path.insert(0, ROOT)PyInstaller 静态分析看不到, 不给 pathex → 打包后from audit_logger import ...ModuleNotFoundError。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 版稳定后再删。