PyInstaller 是 Python 3.11 下最直接、兼容性最好的打包方案,需用 ≥6.0 版本,注意路径处理、资源加载及 GUI/CLI 参数配置。

用 PyInstaller 打包是最直接的选择
Python 3.11 官方不提供内置打包工具,PyInstaller 是目前兼容性最好、开箱即用程度最高的方案。它能自动分析依赖、收集标准库子模块、处理 C 扩展(如 numpy、PIL),且对 3.11 支持已稳定(需用 PyInstaller >= 6.0)。
安装时务必指定版本:
pip install "PyInstaller>=6.0"
低版本(如 5.x)在 3.11 下会报 AttributeError: module 'sys' has no attribute 'abiflags' 或卡在 hook 阶段。
- 确认 Python 和 pip 是 3.11:运行
python --version和pip --version - 避免混用 conda 环境和 pip 安装的 PyInstaller——conda-forge 的
pyinstaller包有时滞后,优先走 pip - 如果项目用了
venv,确保在激活环境下安装和运行pyinstaller
--onefile 和 --onedir 怎么选
--onefile 把所有东西塞进单个 EXE,适合分发;--onedir(默认)生成一个文件夹,含 EXE + _internal 资源目录,启动更快、调试更方便。
立即学习“Python免费学习笔记(深入)”;
3.11 下 --onefile 启动略慢(首次解压资源约 200–500ms),且某些防病毒软件会误报——这不是 bug,是行为特征。
- 开发调试阶段用
--onedir:改代码后只需重打包 EXE,不用重复拷贝整个资源目录 - 发布前加
--onefile --upx-exclude=vcruntime140.dll(若用 UPX 压缩),否则可能触发 Windows 加载失败 - 含 GUI(如
tkinter、PyQt6)的脚本,--onefile必须加--add-binary手动补图标或资源,否则图标丢失或界面空白
打包后运行报错:找不到模块或路径异常
常见错误如 ModuleNotFoundError: No module named 'requests' 或 FileNotFoundError: [Errno 2] No such file or directory: '_internal/data/config.json',本质是运行时路径变了。
PyInstaller 3.11 运行时把资源解压到临时目录,__file__ 指向的是那个临时 EXE 路径,不是原始脚本位置。
- 用
sys._MEIPASS获取资源根路径:import sys<br>if getattr(sys, 'frozen', False):<br> base_path = sys._MEIPASS<br>else:<br> base_path = os.path.dirname(os.path.abspath(__file__))
- 读取同级数据文件别写
open('config.json'),改用open(os.path.join(base_path, 'config.json')) - 第三方包里带的数据(如
certifi的 CA 证书)通常被自动收集,但个别包(如charset_normalizer)需显式加--add-data "charset_normalizer;charset_normalizer"
图标、版本信息、控制台窗口这些怎么加
Windows 上的 EXE 属性(图标、公司名、描述)和是否显示黑窗,靠命令行参数或 spec 文件控制,没有图形界面配置。
- 设图标:
pyinstaller --icon=app.ico script.py(.ico文件必须存在,且尺寸建议包含 256×256) - 隐藏控制台(GUI 程序用):
--noconsole;保留黑窗(命令行工具用):--console(3.11 默认就是--console) - 加版本信息需先生成
version_info.txt,再用--version-file=version_info.txt;内容格式严格,可用pyinstaller --dump-config查默认模板 - 想改进程名(任务管理器里显示的名字),不能只改 EXE 文件名,得用
--name=myapp参数,否则资源加载路径仍按原脚本名解析
真正麻烦的从来不是打包动作本身,而是资源路径硬编码、相对导入、以及第三方包内部的动态路径拼接——这些在 .py 里跑得好好的,一打包就露馅。多打几次 --onedir 版本,用资源管理器打开 _internal 目录看看缺啥,比死盯文档快得多。


















