pyinstaller打包后启动慢主因是冗余模块导入,应使用--exclude-module精准剔除未用顶层包(如matplotlib),避免子模块级排除;辅以--collect-submodules控制资源收集、覆盖或禁用默认hook,并通过--debug=imports验证效果。

PyInstaller打包后启动慢,大概率是带了没用的模块
PyInstaller默认会递归分析 import 链并打包所有它“看到”的模块,包括 matplotlib、scipy、tensorflow 这类重型依赖——哪怕你的代码只写了 import matplotlib.pyplot as plt 却根本没调用绘图函数。这些库加载时会触发大量子模块导入、C扩展初始化、甚至环境检测,直接拖慢启动 1–3 秒。
用 --exclude-module 精准剔除未使用的顶层包
这是最直接、副作用最小的方式。关键在于:必须排除“顶层包名”,而不是子模块;且需在 import 分析完成前生效(即命令行参数早于 --onefile 等)。
-
--exclude-module matplotlib有效;--exclude-module matplotlib.pyplot无效(PyInstaller 不识别子模块级排除) - 多个要排除的包,重复写多次:
--exclude-module scipy --exclude-module pandas --exclude-module sklearn - 如果用了
import seaborn as sns但没画图,加--exclude-module seaborn;它底层依赖matplotlib,所以matplotlib也得一并排除,否则可能报ImportError: No module named 'matplotlib' - 排除后若运行时报
ModuleNotFoundError,说明代码实际用到了——别硬删,改用--hidden-import显式补回需要的少数符号
用 --collect-all 和 --collect-submodules 控制资源收集粒度
某些包(如 pydantic、requests)自带数据文件或插件机制,PyInstaller 会自动收集整个包目录,但你可能只用了核心逻辑。这时手动收比默认全收更轻量。
- 先删掉默认收集:
--exclude-module pydantic - 再只收真正需要的:
--collect-submodules pydantic._internal._generate_schema(注意路径必须是 import 路径,不是文件路径) -
--collect-all是“收全一个包及其所有子模块+数据”,慎用;--collect-submodules更细,适合只取其中一两个子模块 - 验证是否够用:打包后进
dist/xxx/_internal/pydantic/目录,看有没有缺失的.py或.so
启动慢还可能是 hooks 暗中加载了大包
PyInstaller 自带的 hook-*.py 文件(比如 hook-numpy.py)会强制包含整套生态,即使你只用了 np.array。这类 hook 优先级高于命令行 exclude,必须覆盖它。
- 新建目录
hooks/,放一个空的hook-numpy.py(内容就一行:pass),然后加参数--additional-hooks-dir ./hooks - 或者更稳妥:用
--nohooks关掉所有默认 hook,再用--hidden-import显式列出真正需要的模块(如--hidden-import numpy.core._multiarray_umath) - 检查是否生效:打包时加
--debug=imports,搜日志里有没有numpy相关的自动收集记录
真正影响启动速度的从来不是代码体积,而是 import 时触发的动态行为。排除模块只是手段,关键是确认“这段 import 是否真被执行”——加个 print(__name__) 在疑似模块里,跑一遍原生 Python 就知道它到底参没参与启动流程。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











