https://github.com/touken928/uvpacker
把标准
pyproject.toml项目变成「拷到 Windows 机器上就能跑」的自包含应用目录------不需要目标机安装 Python,不需要 PyInstaller,甚至不需要你在 Windows 上构建。
它解决什么问题
Python 生态的打包一直是个痛点:
-
PyInstaller 体积大、启动慢、跨平台支持有限,配置复杂且产物难以预期;
-
Nuitka 需要编译,构建时间长,调试门槛高;
-
传统方式往往要求你在 Windows 上 才能打出 Windows 包,CI/CD 流程被平台绑架。
uvpacker 走了一条不同的路:它以 uv 为依赖解析引擎,以 CPython 官方嵌入式运行时(Embedded Distribution) 为目标运行时,产出的是一个结构清晰、可压缩、可拷贝的 应用目录 ,而非单文件 exe。你可以在 Linux、macOS 或 Windows 上完成整个构建。
核心功能
| 功能 | 说明 |
|---|---|
| 跨平台构建 | 依赖解析目标锁定 win_amd64,从任意 OS 打出 Windows 包(纯 Python 项目或已有 Windows wheel 的项目均可) |
| 自包含运行时 | 内嵌官方 CPython Embedded Runtime,目标机器无需安装系统 Python |
| 声明式配置 | 全部基于标准 pyproject.toml 的 [project.scripts] / [project.gui-scripts],零额外配置文件 |
| 原生启动器 | 由 C 编写的 console.exe / gui.exe 模板生成 <script>.exe,控制台程序和 GUI 程序各自走对应子系统 |
| 包内嵌入 | 你的项目包以 zip 归档形式附加到 .exe 尾部,启动时内存导入;第三方依赖留在 packages/ |
| 轻度混淆 | 源码 .py 编译为 .pyc 后删除原始文件(非加密,但避免明文暴露) |
| 资源嵌入 | 通过 importlib.resources.files 访问包内资源,启动器的内存加载器原生支持 |
| 缓存机制 | 嵌入式 Python 运行时下载一次后缓存,重复构建无需重新下载 |
使用步骤
1. 准备项目
确保你的 pyproject.toml 符合上述要求,推荐使用uv创建。
uv init --package
以下是一个最小示例
[project]
name = "my-app"
version = "1.0.0"
requires-python = "==3.12.*"
dependencies = [
"requests",
]
[project.scripts]
my-app = "my_app.main:main"
[build-system]
requires = ["uv_build>=0.11.2,<0.12.0"]
build-backend = "uv_build"
2. 一行命令打包
推荐使用 uvx 直接运行,无需全局安装:
# 默认输出到 ./dist/<项目名>/
uvx uvpacker build path/to/my-app
# 指定输出目录
uvx uvpacker build path/to/my-app -o path/to/output
3. 查看产物
构建完成后,输出目录结构如下:
dist/my-app/
runtime/ # Windows 嵌入式 CPython 运行时
packages/ # 第三方依赖(win_amd64)
my-app.exe # 控制台启动器(来自 [project.scripts])
如果你的项目声明了 [project.gui-scripts],则会额外生成无控制台窗口的 GUI 启动器。
4. 分发
将整个 dist/my-app/ 目录压缩为 zip 或直接拷贝到 Windows 机器上,双击 .exe 即可运行------无需安装任何运行时。
适用场景与限制
适合:
-
纯 Python 项目,希望从 macOS/Linux CI 直接产出 Windows 分发包
-
需要声明式、可预期的打包流程,不想维护复杂构建脚本
-
GUI 应用(PySide6 等)或 CLI 工具的 Windows 分发
限制:
-
不交叉编译 C 扩展------如果你的项目自带 C 扩展源码,需在 Windows 上构建,或预先准备好 Windows wheel
-
项目包自身若包含
.pyd/.dll等原生二进制,当前的内存嵌入模式不支持(第三方依赖中的原生二进制不受影响,仍保留在packages/)