Python打包方法
本文全面对比了PyInstaller和Nuitka两种Python打包工具的优劣势,帮助开发者选择最适合自己项目的打包方案。
PyInstaller 与 Nuitka 对比
基本介绍
在Python开发中,将代码打包成可执行文件是一个常见需求。目前市场上有多种打包工具,其中PyInstaller和Nuitka是两个广受欢迎的选择。
PyInstaller
PyInstaller是一个成熟的Python打包工具,它通过分析Python脚本的导入和依赖关系,将所有必要的文件打包到一个目录或单个可执行文件中。
- 工作原理:PyInstaller使用Python的
inspect
和marshal
模块分析代码依赖,然后将Python解释器和所有依赖打包在一起。
Nuitka(推荐)
Nuitka是一个相对较新的Python编译器,它将Python代码转换为C++代码,然后编译成本地可执行文件。
- 工作原理:Nuitka将Python代码转换为C++代码,然后使用C++编译器(如GCC、MSVC)编译成本地可执行文件。
共同目标
这两个工具都能实现以下目标:
隐藏源码
- PyInstaller:通过设置key对源码进行加密,但仍可被反编译工具破解
- Nuitka:将Python源码转成C++(生成二进制的
.pyd
文件),大幅提高反编译难度
方便移植:用户无需安装Python或第三方包即可运行程序
跨平台支持:都支持在Windows、macOS和Linux上打包和运行
性能对比
方面 | PyInstaller | Nuitka |
---|---|---|
文件体积 | 😞 较大 | 🚀 较小 |
打包速度 | ⏱️ 较慢 | ⚡ 较快 |
启动速度 | 🐢 慢 | 🐇 快 |
运行性能 | 与Python解释器相同 | 有一定性能提升 |
实际体验对比
工具 | 体验 | 特点 |
---|---|---|
PyInstaller | 😞 很差,但是兼容性好 | • 深度学习项目打包后的exe文件体积巨大(接近3GB) • 打包速度慢(可能需要30分钟以上) • 启动速度慢(冷启动可能需要10秒以上) • 对复杂依赖处理能力有限 • streamlit打包支持良好 |
Nuitka | 🚀 真香,但是兼容性差 | • 同样的项目,生成的exe文件仅7MB • 打包速度快(10分钟以内) • 启动速度快(几乎瞬时启动) • 运行性能有10-30%的提升 • streamlit打包支持很差 |
PyInstaller 的安装及使用
🔧 安装步骤
只需一行命令即可安装 PyInstaller:
1 | pip install pyinstaller |
📂 项目结构示例
以下是一个典型的 Python 项目结构:
1 | ├─utils // 自定义工具模块 |
🚀 打包命令
推荐使用多文件分发模式(--onedir
)生成可执行文件,这种模式下依赖文件单独存放,具有多项优势:
1 | pyinstaller --onedir \ |
⚙️ 参数详解
参数 | 说明 |
---|---|
--onedir |
推荐选项:将所有文件打包到一个文件夹中 • ✅ 便于管理和更新依赖 • ✅ 启动速度更快 • ✅ 支持动态加载模块 |
--onefile |
不推荐:将所有文件打包成单个可执行文件 • ❌ 文件体积较大 • ❌ 启动速度慢 • ❌ 不支持动态加载 |
--icon=logo.ico |
指定生成的可执行文件图标 |
--name=demo |
指定输出的可执行文件名称 |
--clean |
在构建前清理 PyInstaller 缓存和临时文件 |
--noconsole |
运行时不显示控制台窗口(适用于 GUI 程序) |
--add-data="source:dest" |
添加额外的非 Python 文件到包中 |
--hidden-import=pkg |
添加 PyInstaller 无法自动检测到的导入 |
--additional-hooks-dir=path |
指定自定义钩子脚本目录 |
📦 打包结果
打包过程通常需要 5-30 分钟(取决于项目大小),完成后的目录结构如下:
1 | ├─utils // 原始源码文件夹(不变) |
🔍 高级用法
使用 spec 文件进行自定义配置
对于复杂项目,可以通过 spec 文件进行更精细的控制:
生成 spec 文件:
1
pyi-makespec --onefile demo.py
编辑配置:修改
demo.spec
文件,添加自定义配置使用 spec 文件构建:
1
pyinstaller demo.spec
加密打包的 Python 字节码
可以使用 --key
参数对打包的 Python 字节码进行简单加密:
1 | pyinstaller --onefile --key=your_secret_key demo.py |
注意:这种加密方式只能提供基本保护,不能完全防止逆向工程。
🌟 Streamlit 应用打包指南
Streamlit 应用需要特殊处理才能正确打包。完整步骤如下:
1. 创建启动脚本
由于 PyInstaller 无法直接启动 Streamlit 应用,是通过streamlit run <你的脚本>.py实现,因此需要创建一个中间启动脚本 run.py
:
1 | import streamlit.web.cli as stcli |
关键点:
- 正确处理路径,判断当前路径是打包后启动的临时文件路径,还是平时直接运行脚本的路径,否则打包后启动exe程序会报错说找不到<你的脚本>.py文件,那样只能复制<你的脚本>.py跟exe在同个目录才能正常运行。
- 禁用开发模式,developmentMode设置为false,否则启动的时候浏览器会自动跳到3000端口,而不是streamlit服务的端口
2. 创建 hooks 文件
创建目录和文件 ./hooks/hook-streamlit.py
:
1 | from PyInstaller.utils.hooks import copy_metadata |
3. 生成spec文件
- 方法一(仅生成spec,推荐!)
1
pyi-makespec run.py
- 方法二(生成spec同时打包,速度慢)
1
pyinstaller --additional-hooks-dir=./hooks run.py --clean
这一步的目的是生成 run.spec
文件,为下一步编辑做准备。
4. 编辑 spec 文件
修改生成的 run.spec
文件,确保包含所有必要的依赖:
1 | # -*- mode: python ; coding: utf-8 -*- |
重要配置:
datas
:声明所有静态资源和必要文件hiddenimports
:添加隐式导入的模块,打包后报错缺少的模块都添加在这里hookspath
:自定义 PyInstaller hooks 路径,用于处理特定模块的打包逻辑
5. 执行最终打包
1 | pyinstaller run.spec --clean |
完成上述步骤后,你将获得一个可以独立运行的 Streamlit 应用程序。
Nuitka 的安装及使用
安装步骤
使用 pip 安装 Nuitka:
1
pip install nuitka
下载并安装 C++ 编译器
使用指南
对于依赖较多第三方库的项目(如 torch
, cv2
, numpy
, pandas
, onnxruntime
等),**建议只将自定义代码转为 C++**,而保留这些大型第三方库。
示例项目结构
1 | ├─utils // 源码 1 文件夹 |
打包命令
使用以下命令生成 exe 文件(调试模式):
1 | nuitka --standalone \ |
参数说明
参数 | 说明 |
---|---|
--standalone |
生成独立的可执行文件,方便移植到其他机器,无需安装 Python |
--nofollow-imports-to |
指定不需要被编译的第三方库,通常是一些大型依赖库。多个包用逗号分隔 |
--follow-import-to |
指定需要编译成 C++ 的源码文件夹或模块,这些通常是你自己编写的代码 |
--include-package |
指定需要完整打包但不编译的包,这些包通常是运行必需但无法自动检测到的 |
--output-dir |
指定编译输出的目录路径 |
--include-data-dir |
指定需要打包的数据文件夹,格式为源路径=目标路径 |
--include-data-file |
指定需要打包的单个数据文件,如模型文件、配置文件等,格式为源路径=目标路径 |
--windows-icon-from-ico |
指定生成的可执行文件图标路径 |
--windows-disable-console |
运行可执行文件时不弹出控制台窗口,适用于GUI程序 |
--enable-plugin |
启用特定插件支持,如qt-plugins 用于Qt应用 |
--show-progress |
显示编译进度 |
--show-memory |
显示编译过程的内存使用情况 |
--python-flag=no_site |
禁用site模块,可以减少一些不必要的依赖 |
打包结果
经过约 1 分钟的编译后,目录结构如下:
1 | ├─utils // 源码 1 文件夹 |
🌟 Streamlit 应用打包指南
1. 创建启动脚本
由于 nuitka 无法直接启动 Streamlit 应用,是通过streamlit run <你的脚本>.py实现,因此在<你的脚本>.py后添加以下代码:
1 | import streamlit.config |
2. nuitka打包
1 | nuitka --standalone \ |
3.复制依赖库
- 运行helloworld.exe查看报错提示的缺失库
- 在everything下搜索对应环境的缺失库文件,复制到out/dist/文件夹下
完成上述步骤后,你将获得一个可以独立运行的 Streamlit 应用程序。
常见问题及解决方案
第三方库缺失问题
- 问题:运行生成的 exe 文件时,可能会报错:
no module named torch, cv2
等 - 解决方法:找到这些库的安装路径(例如
python3.7\Lib\site-packages
),将对应的文件夹(如numpy
,cv2
)复制到demo.dist
目录下,其中该库的dll和dist都需要一起复制进来
完成上述步骤后,exe 文件即可正常运行!
总结
- 如果你需要快速、高效地将 Python 项目打包为 exe 文件,Nuitka 是一个非常优秀的工具
- 相比于 PyInstaller,Nuitka 在文件体积、打包速度和运行效率上都有显著优势
实用工具推荐
- 将图片转为
.ico
格式的网站:比特虫