有时你需要把 Python 程序分享给没有安装 Python 环境的用户,或者部署到一台干净的服务器上。这时候,将脚本打包成独立的可执行文件就是一个非常实用的方案。PyInstaller 是目前最成熟、使用最广的 Python 打包工具。
PyInstaller 是什么
PyInstaller 会分析你的 Python 脚本,找出所有依赖的模块和库,然后把 Python 解释器、你的源码(编译成字节码)以及所有依赖一并打包到一个文件夹或单个可执行文件中。对方拿到后直接双击或命令行调用就能运行,无需安装 Python。
安装与基本用法
- 安装:
pip install pyinstaller - 基础打包命令:在脚本所在目录运行
pyinstaller your_script.py
这会在当前目录下生成 dist/your_script/ 文件夹,里面包含 your_script(Linux/macOS)或 your_script.exe(Windows)以及一系列依赖库。把整个文件夹发给用户即可运行。
常用打包选项
- 打包成单个文件:
--onefile(缩写-F)
pyinstaller --onefile your_script.py
生成单个 .exe(或可执行文件),方便分发,但启动时需解压到临时目录,首次启动可能稍慢。
- 不显示控制台窗口(仅 Windows 有用):
--noconsole(缩写-w)
当你打包的是 GUI 程序,不想让黑窗口出现时使用。
- 指定输出目录:
--distpath ./output可以自定义生成位置。 - 添加图标:
--icon=myicon.ico让生成的.exe带上自定义图标(Windows 有效)。 - 额外包含数据文件:如果你的脚本需要读取配置文件、图片等,用
--add-data "src;dest"(Windows 用分号分隔,Linux/macOS 用冒号)。例如:
pyinstaller --add-data "config.ini;." main.py
跨平台打包的真实原理
PyInstaller 不支持交叉编译。也就是说:
- 你要生成 Windows 的
.exe,就得在 Windows 上运行 PyInstaller。 - 你要生成 macOS 的可执行文件,就得在 macOS 上运行。
- Linux 同理。
所以真正的“跨平台打包”意味着你要为每个目标平台准备对应的打包环境,逐一构建。很多项目会使用 CI/CD(如 GitHub Actions)同时构建 Windows、macOS、Linux 的安装包,每次发布时自动生成全平台产物。
打包后的目录结构
如果不用 --onefile,dist/your_script/ 里面大致包含:
- 主可执行文件(
your_script) - 依赖的
.so/.dll/.dylib等动态库 python.dll(Windows)或libpython.so(Linux)- 标准库模块(以
.pyc形式存在)
你会发现体积不小,因为 Python 解释器和依赖库全都打进去了。一个最简单的 print("hello") 打包出来大约 8-15MB(不同平台差异)。
常见问题与解决方案
- 打包后运行报找不到模块:多数是因为某些依赖采用动态导入,PyInstaller 分析不到。可以通过
--hidden-import=module_name显式添加。 - 文件路径问题:打包后脚本运行时,工作目录可能不是脚本源码所在目录。使用
sys._MEIPASS(PyInstaller 自带的临时解压目录)获取资源文件的正确路径。
import sys, os
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(__file__)
- 杀毒软件误报:用
--onefile打包的 exe 有时会被误报为病毒,因为很多恶意软件也用这种打包方式。没有绝对解决办法,通常签名和提交给杀软厂商可改善。 - 文件体积过大:尽量用虚拟环境打包(只安装必需依赖),避免全量 anaconda 环境。venv + 少量依赖可显著减小体积。
- 动态库冲突:如果依赖的二进制库(如 opencv、numpy)在不同平台有不同的底层实现,确保在目标平台打包时会自动匹配,打包结果一般没问题。
小结
PyInstaller 是“一键打包”的利器,适合制作发给用户的小工具、运维脚本、桌面 GUI 等场景。记住核心原则:在哪用,就在哪打包。在工程化实践中,可以通过 CI 流水线实现真正的一键全平台发布。