Python 生成可执行文件附录#
将 Python 脚本打包为独立可执行文件,可在无 Python 环境的机器上运行,便于分发与部署。
核心概念#
为何需要可执行文件#
- 无 Python 环境:目标机器未安装 Python 或版本不一致时仍可运行。
- 便于分发:单文件或单目录即可交付,无需配置依赖。
- 保护源码:打包后用户难以直接查看或修改源码(非强加密)。
实现方式概览#
| 方式 | 代表工具 | 原理 |
|---|---|---|
| 打包器 | PyInstaller、cx_Freeze | 将解释器、依赖与脚本打包成目录或单文件,运行时解压/加载。 |
| 编译型 | Nuitka | 将 Python 编译为 C,再编译为原生二进制,无内置解释器。 |
工具选型简表#
| 工具 | 适用场景 | 跨平台 | 依赖复杂度 | 体积/启动 |
|---|---|---|---|---|
| PyInstaller | 通用、快速打包 | 是 | 低,自动分析多 | 单文件较大、首次略慢 |
| cx_Freeze | 需精细控制、跨平台一致 | 是 | 中,常需写配置 | 目录分发,可控 |
| Nuitka | 追求性能、体积或兼容性 | 是 | 高,需 C 编译器 | 体积与启动更优,编译慢 |
PyInstaller(推荐首选)#
安装#
pip install pyinstaller单文件与目录打包#
- 单文件:产出单个 exe(Windows)或可执行文件,运行时解压到临时目录。适合分发。
- 目录:产出一个目录,内含可执行文件与依赖。启动更快,便于调试。
# 单文件(最常用)
pyinstaller --onefile script.py
# 目录模式(默认)
pyinstaller script.py常用参数#
| 参数 | 说明 |
|---|---|
--onefile / -F | 打包成单文件 |
--name / -n | 指定生成的可执行文件名 |
--icon / -i | 指定图标(Windows .ico) |
--add-data | 将数据文件/目录打进包(格式:src;dest 或 src:dest) |
--hidden-import | 显式加入未自动检测到的模块 |
--console / --noconsole | 是否保留控制台(GUI 程序常用 --noconsole) |
示例:
pyinstaller --onefile --name myapp --icon app.ico \
--add-data "config.json;." \
--hidden-import pandas \
script.py打包后访问资源路径#
单文件运行时,脚本所在目录是临时解压目录,需用 sys._MEIPASS 定位资源:
import sys
import os
def resource_path(relative_path):
"""获取打包后资源文件的绝对路径。"""
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath('.'), relative_path)
config_path = resource_path('config.json')spec 文件#
spec 是 PyInstaller 的构建规格文件(Python 脚本),用于精确控制打包内容与流程,便于版本管理、复现构建。
生成与使用
- 首次执行
pyinstaller script.py会在当前目录生成script.spec。 - 之后用
pyinstaller script.spec构建,命令行参数以 spec 为准;修改 spec 即可调整打包结果,无需长命令。
主要可配置项
| 区块 | 说明 |
|---|---|
Analysis | 入口脚本、依赖、pathex、hiddenimports、datas(数据文件)、excludes 等。 |
PYZ | 打包进 PYZ 的模块(通常自动)。 |
EXE | 单文件可执行:a(Analysis 实例)、console、icon、name 等。 |
COLLECT | 目录模式:收集 exe、依赖、数据到输出目录(单文件模式无此块)。 |
示例(单文件)
# script.spec 精简示例
# 执行: pyinstaller script.spec
a = Analysis(
['script.py'],
pathex=[],
binaries=[],
datas=[('config.json', '.')],
hiddenimports=['pandas'],
excludes=['tkinter'],
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
name='myapp',
console=False,
icon='app.ico',
)何时用 spec
- 需要稳定、可复现的构建(CI 或团队协作)。
- 依赖、数据文件、排除项较多,命令行难以维护。
- 多入口或需在构建前后执行自定义逻辑(spec 中可写 Python 代码)。
cx_Freeze#
安装与基本用法#
pip install cx_Freeze命令行快速打包:
# 将 script.py 打包为可执行文件(默认生成目录)
cxfreeze script.py --target-dir dist使用 setup.py 配置(推荐)#
便于控制依赖、多脚本与数据文件:
from cx_Freeze import setup, Executable
build_exe_options = {
'packages': ['numpy', 'pandas'],
'excludes': ['tkinter'],
'include_files': ['config.json'],
}
setup(
name='myapp',
version='1.0',
description='My Application',
options={'build_exe': build_exe_options},
executables=[Executable('script.py', target_name='myapp')],
)然后执行:
python setup.py build与 PyInstaller 对比#
- 配置:cx_Freeze 常用
setup.py或配置文件,适合项目化、多入口;PyInstaller 命令行即可完成大部分场景。 - 适用:需严格控制包含/排除模块、或与 setuptools 集成时,cx_Freeze 更灵活;日常单脚本分发优先 PyInstaller。
Nuitka#
特点#
- 将 Python 编译为 C,再编译为原生二进制,无内置解释器。
- 运行性能与启动速度通常优于打包器方案;体积可能更小。
- 编译需 C 编译器(如 Windows 上的 MinGW64/MSVC),编译时间较长。
基本命令#
pip install nuitka
# 基本编译(生成可执行文件)
nuitka script.py
# 单文件模式(需 onefile 插件)
nuitka --onefile script.py
# 指定输出名
nuitka --output-filename=myapp script.py使用注意#
- 首次使用需安装 C 编译器,Windows 上 Nuitka 会提示下载依赖。
- 部分动态特性(如大量
eval、复杂反射)可能受限。 - 适合对性能、体积或兼容性有明确需求的场景,一般分发可优先 PyInstaller。
常见问题与细节#
杀毒软件误报#
- 打包器生成的 exe 常被误报为病毒(行为类似自解压、内存加载)。
- 应对:代码签名(Windows 需证书)、上传厂商白名单、或改用目录分发 + 说明用户添加信任。
体积过大#
- 原因:打包了完整解释器与依赖(如 numpy、PyQt)。
- 应对:用虚拟环境只装必要依赖;
--exclude-module排除不需要的库;考虑 Nuitka 或 UPX 压缩(注意部分环境对 UPX 敏感)。
缺失依赖(ImportError / ModuleNotFoundError)#
- 动态导入或插件式加载的模块可能未被自动分析到。
- 应对:PyInstaller 用
--hidden-import;cx_Freeze 在packages/includes中显式加入;Nuitka 用--include-module。
路径与 sys._MEIPASS#
- 单文件运行时,当前工作目录可能是用户启动目录,而资源在临时目录。
- 始终用
sys._MEIPASS(或封装好的resource_path)定位打包进去的数据文件,避免写死相对路径。
多平台注意#
- Windows:产出
.exe;GUI 程序可用--noconsole隐藏控制台。 - Linux / macOS:产出无扩展名或平台约定名称的可执行文件;注意动态库与权限。
- 各平台需在对应系统下分别打包,无法在一个平台上直接生成另一平台的可执行文件。