技能|PyInstaller重打包与dist避坑法
> 与知识库 05-技能库/技能|PyInstaller重打包与dist避坑法.md 一一对应(三处同步之一)。
适用场景
源码/数据更新后重新构建桌面壳。spec 里 datas 会把 data/*.db 捎带进包,但需保证与源库一致。
触发词
重打包、PyInstaller、COLLECT 删除被拦、dist 构建失败、打包后数据不对、sync_data_to_dist、_internal/data
操作步骤
- 先把旧
dist/应用名改名移走(如dist/_prev_build_bak):沙箱/安全策略会拦 PyInstaller COLLECT 阶段的批量删除(本次 137 个文件超限),不改名的直接后果是EXIT=1构建失败。用改名而不是删除。 - 构建:
pyinstaller --noconfirm <应用名>.spec(用 venv 里的Scripts/pyinstaller.exe)。耗时长,放后台跑并重定向日志。 - 确认 EXIT=0,再检查
dist/应用名/应用名.exe存在。 - 同步数据:
python scripts/sync_data_to_dist.py把源data/*.db覆盖到dist/应用名/_internal/data(spec 构建时已捎带,此步保证逐字节一致)。 - 验打包内数据:打开
dist/应用名/_internal/data/*.db数 shows / flow_records,与源库核对(本次 82 / 2677)。 - 冻结路径确认:
backend/db.py的 DATA_DIR 在 frozen 下解析到_internal/data,所以同步目录必须是这里。 - 清理:确认新构建无误后,把第 1 步移走的旧构建挪到临时区(不要 bulk delete)。
注意边界
- 构建日志务必落盘:失败信息在几千行输出里,不落盘根本找不到。
--noconfirm避免交互确认卡住后台任务。- 打包内的 DB 是给最终用户的,必须与源库一致;spec 的 datas 只在构建那一刻拷贝,之后源库再变不会自动跟进。
- 旧构建用改名(mv)移走,不用 rm -rf——既避开删除拦截,也留了回退。
反例避雷
| 反例 | 为什么错 | 正确做法 |
|---|---|---|
| 让 PyInstaller 直接覆盖旧 dist | COLLECT 批量删被拦 → EXIT=1 构建失败 | 先把旧 dist 改名移走再构建 |
| 用 rm -rf 清旧构建 | 触发安全策略拦截 / 不可逆 | 用 mv 改名移走 |
| 构建完不同步数据 | 包里是构建那一刻的旧库 | 跑 sync_data_to_dist.py 并核对计数 |
| 去 dist 根找数据目录 | 实际数据在 _internal/data | 按 db.py 的 frozen 路径解析 |
| 用裸解释器跑 pyinstaller | 缺依赖 / 找不到命令 | 用 venv 的 Scripts/pyinstaller.exe |
关联
- 总纲技能:
05-技能库/技能|安检数据导入与发版打包流程.md - 项目:
D:\安检系统(FastAPI + SQLite 按年分库 + PyInstaller/Inno Setup 桌面壳) - 文件:
安检系统.spec、scripts/sync_data_to_dist.py、backend/db.py
版本记录
| 版本 | 日期 | 变更 |
|---|---|---|
| v1.0.0 | 2026-09-29 | 首版实战固化(V4.5.7):旧 dist 改名后构建 EXIT=0,同步后包内 82 展 / 2677 流水与源库一致 |