PyInstaller 打包 PaddleOCR 应用瘦身实录:从 779MB 到 292MB
前言:最近用 PyQt6 + PaddleOCR 做了一个离线合同生成器(OCR 识别需方抬头、Excel 导入明细、自动编号、导出 PDF),功能跑通后用 PyInstaller 打包 EXE,结果 dist 目录 779MB——一个"填表工具"比Photoshop 还大。本文记录我是怎么定位脂肪来源、安全地砍到 292MB,且 OCR 功能毫发无损的。
一、肥从哪来:先量化,再动刀
瘦身第一原则:不要凭感觉删,先量出每一块的体积。
跑完一目了然,四大元凶:
|
元凶 |
体积 |
为什么会进来 |
|
paddlepaddle 推理库 |
~300MB |
PaddleOCR 的硬依赖,大头 |
|
opencv-python (cv2) |
~90MB |
PaddleOCR 依赖,但我只用了图像预处理的一小部分 |
|
pandas |
~60MB |
被连带拉入,但我读写 Excel 只用 openpyxl |
|
modelscope 及缓存 |
~80MB |
早期实验的遗留,正式版根本没用到 |
|
numpy |
~40MB |
paddle 的依赖,动不了,但能选轻量版 |
二、第一刀:exclude-module 排除假依赖
PyInstaller 会沿 import 链把"可能用到"的包全部打进去。用 spec 文件的 excludes 精确排除:
注意两点:① cv2 不要盲目排除(PaddleOCR 检测模块真需要),后文有替代方案;② 排除后必须全功能回归测试,我第一次排掉了 openpyxl 的一个间接依赖,Excel 导入直接白屏。
三、第二刀:换轻量模型
PaddleOCR 默认可能带 server 级检测/识别模型。换成 mobile 版,单个模型从几十 MB 降到几 MB:
mobile 版对"打印体合同抬头"这类规整文本的识别率与 server 版几乎没有差异——我的场景是识别公司抬头的统一社会信用代码和名称,都是印刷体,实测完全够用。模型精度要跟场景匹配,不要默认越贵越好。
四、第三刀:cv2 的瘦身替代
cv2 的 90MB 里大部分是视频模块、DNN 模块等我用不到的东西。两个选择:
- 换
opencv-python-headless(去掉 GUI 依赖,省 20MB 左右);
- 更激进:预处理只用 PIL/Pillow 实现(缩放、灰度、二值化),把 cv2 从依赖树里整个摘掉——省 90MB,但需要回归验证 OCR 检测效果。
我选了方案 2,实测 PaddleOCR 在 Pillow 预处理后的图像上工作正常。
五、结果与体积清单
功能回归:OCR 抬头识别、Excel 十列明细导入、SLBJ+日期+序号的编号生成、PDF 导出,全部正常。
六、三条经验
- 先量化再动刀:
os.walk十行代码,比任何"经验之谈"都可靠;
- excludes 要配回归测试:PyInstaller 的依赖树推断保守,砍之前先跑全功能用例;
- 模型选型看场景:印刷体识别 mobile 版足够,手写体/复杂版面才需要 server 版——这一刀砍得最没有心理负担。
下一个优化方向是 UPX 压缩和按需下载模型(首启时拉取),预计还能再降 20%,留待下篇。
(完)环境:Windows 10 / Python 3.11 / PyInstaller 6.x / PaddleOCR(PP-OCRv4 mobile)/ 2026-10 实测
- 点赞
- 收藏
- 关注作者
评论(0)