fspack
极速 Python 项目打包器(cargo 风格短命令)。
fspack 将 Python 项目打包为可执行文件与跨平台安装包:用 embed python(Windows)或 python-build-standalone(Linux)提供运行时,C loader 配置环境并调用用户脚本,NSIS 生成 Windows 安装包、dpkg-deb 生成 Linux .deb 与 tar.gz 便携包。命令风格参考 cargo,常用操作均可用两字母短命令完成。
特性
- cargo 风格短命令:
fsp b打包、fsp r运行、fsp c清理、fsp p生成安装包 - 零依赖入侵:不需修改用户源码,自动分析 import 推断第三方依赖
- embed python 运行时:Windows 用官方 embed python zip,Linux 用 indygreg python-build-standalone
- C loader 启动器:动态加载 libpython,烧入入口路径,mingw/gcc 编译为原生可执行文件
- 跨平台安装包:
fsp p按目标平台生成 Windows NSIS 安装包(含开始菜单/桌面快捷方式、卸载器、中英文双语)或 Linux .deb + tar.gz 便携包 - 双平台支持:Windows(embed + mingw 交叉编译)、Linux(python-build-standalone + gcc)
- 多入口打包:
[tool.fspack.entries]声明多个入口,单个项目生成多个 exe 共享 runtime/依赖/源码,支持 cli/gui/web 混合类型 - 国内镜像:默认阿里云 PyPI 与 embed python 镜像,
--mirror切换 - 彩色进度显示:rich 驱动的步骤进度(> 准备运行时 / √ 构建完成),错误/警告/一般消息颜色区分,
-v开启 DEBUG 日志
安装
pip install fspack
或使用 uv:
uv add fspack
快速上手
在 Python 项目根目录(含 pyproject.toml)执行:
# 打包当前项目(生成 dist/<name>.exe 与 dist/runtime/)
fsp b
# 运行已打包项目
fsp r
# 生成安装包到 dist/release/(Windows: <name>-setup.exe / Linux: <name>_<ver>_amd64.deb + <name>-<ver>-linux.tar.gz)
fsp p
# 清理 dist/
fsp c
也可指定项目目录与选项:
fsp b /path/to/project --mirror aliyun --py-version 3.11.9 --target windows
命令参考
全局选项:-V/--version 显示版本,-v/--verbose 开启 DEBUG 级别日志。
| 命令 | 别名 | 说明 |
|---|---|---|
fsp build |
fsp b |
打包项目,生成 dist/ 下可执行文件与运行时 |
fsp run |
fsp r |
运行已打包项目(Linux 原生直跑,.exe 自动用 wine) |
fsp clean |
fsp c |
清理 dist/ 目录 |
fsp package |
fsp p |
生成安装包(Windows NSIS / Linux .deb + tar.gz) |
fsp build
fsp b [project] [--mirror <name>] [--py-version <ver>] [--target <platform>]
project:项目目录,默认当前目录--mirror:镜像源(aliyun/huawei/tsinghua),默认 aliyun--py-version:embed python 版本,默认 3.11.9(Windows)/ 3.11.10(Linux,匹配 python-build-standalone release)--target:目标平台(windows/linux),默认当前平台
fsp run
fsp r [project] [--entry <name>] [--debug] [-- <args>...]
project:项目目录,默认当前目录--entry <name>:多入口项目指定要运行的入口名(与[tool.fspack.entries]键匹配),单入口项目可省略--debug:用 embed python 直跑入口脚本(绕过 GUI loader,输出可见)-- <args>:透传给目标程序的参数(--分隔)
fsp clean
fsp c [project]
fsp package
fsp p [project] [--mirror <name>] [--py-version <ver>] [--target <plat>] [--no-build]
--target:目标平台(windows/linux),默认当前平台--no-build:跳过重建,直接打包已有 dist(需先fsp b)
按目标平台分发:Windows 走 NSIS 生成 dist/release/<name>-setup.exe;Linux 走 dpkg-deb 生成 dist/release/<name>_<ver>_amd64.deb 与 dist/release/<name>-<ver>-linux.tar.gz 便携包。
工作原理
fsp b 构建流水线:
- 解析
pyproject.toml,识别项目名、版本、入口模块、CLI/GUI 类型 - 下载运行时:Windows 下载 embed python zip 并解压到
dist/runtime/;Linux 下载 python-build-standalone tar.gz 并解压到dist/runtime/python/ - 分析依赖:AST 扫描源码 import,分类标准库/本地/第三方,与
pyproject.toml声明依赖比对 - 补充内置库(仅 Windows):AST 检出
tkinter使用时,从 python-build-standalone Windows 构建提取 tkinter 组件(纯 Python 包 +_tkinter.pyd+ Tcl/Tk 运行时脚本)补充到 runtime,按版本缓存 zip 避免重复下载 - 下载 wheel:用 dev python 的
pip download拉取目标平台 wheel,解包到dist/runtime/Lib/site-packages/(Windows)或dist/runtime/python/lib/python3.X/site-packages/(Linux) - 写 _pth(仅 Windows):覆盖
runtime/python3X._pth,注册 site-packages 与..\src路径 - 复制源码:项目源码复制到
dist/src/,排除 dist/build/.venv 等构建产物 - 生成 C loader:按平台模板生成 C 源码(烧入入口脚本相对路径),mingw(Windows)或 gcc(Linux)编译为可执行文件
dist 布局:
dist/
├── <name>.exe # C loader 启动器
├── runtime/ # Python 运行时
│ ├── python311.dll # Windows embed
│ ├── python311._pth
│ └── Lib/site-packages/ # 第三方依赖
├── src/ # 用户源码
└── release/ # 安装包(fsp p 产出)
├── <name>-setup.exe # Windows NSIS
├── <name>_<ver>_amd64.deb # Linux .deb
└── <name>-<ver>-linux.tar.gz # Linux 便携包
多入口打包
单个项目可通过 [tool.fspack.entries] 声明多个入口,每个入口生成独立 exe,
共享 runtime/依赖/源码。每个入口按自身脚本 import 推断 CLI/GUI 类型,支持
cli/gui/web 混合。
[project]
name = "my_app"
version = "0.1.0"
dependencies = ["PySide2>=5.15.2", "flask"]
[tool.fspack.entries]
cli = "cli.py" # 生成 cli.exe(CLI 类型)
gui = "gui.py" # 生成 gui.exe(GUI 类型,加 -mwindows)
web = "web.py" # 生成 web.exe(CLI 类型)
fsp b # 构建:生成 cli.exe/gui.exe/web.exe 三个入口
fsp r --entry cli # 运行 cli 入口
fsp r --entry gui # 运行 gui 入口
fsp r --entry web # 运行 web 入口
多入口模式下每个入口写入 <name>.entry 文件,C loader 运行时按
<exe_basename>.entry 查找入口脚本。单入口项目(无 [tool.fspack.entries])
仍写 .entry 文件,向后兼容。
示例
examples/ 下提供多类典型项目验证打包效果(下划线命名者由 slow 端到端测试覆盖):
| 示例 | 类型 | 说明 |
|---|---|---|
| cli_helloworld | 无库 CLI | 最小示例,验证基础流水线 |
| cli_tool | 有库 CLI | requests 依赖,验证 wheel 下载与解包 |
| cli_complex | 无库 CLI | 展示型,多文件结构 |
| cli_office | 有库 CLI | pypdf 依赖,uv workspace 成员 |
| gui_calc | 有库 GUI | PySide6 依赖,验证 GUI 快捷方式与 DLL 搜索 |
| pyside2_app | 有库 GUI | PySide2 依赖,验证 requires-python 版本自动解析 |
| pyqt5_cli | 有库 GUI | PyQt5 依赖,验证 Python 3.12 兼容 |
| tk_app | 有库 GUI | tkinter 内置库打包,验证 TkinterBundler 从 standalone 提取补充到 embed python |
| pygame_cli | 有库 pygame | pygame 依赖,验证多媒体库打包 |
| pygame_snake | 有库 pygame | pygame 贪吃蛇,验证 dummy 驱动运行 |
| web_app | 有库 web | flask 依赖,验证 web 框架打包 |
| multi_entry | 多入口混合 | cli+gui+web 三入口共享 runtime/依赖,验证 [tool.fspack.entries] 多入口打包 |
平台支持
| 平台 | 运行时 | 编译器 | 安装包 |
|---|---|---|---|
| Windows | embed python(python.org) | mingw-w64 交叉编译 | NSIS(.exe) |
| Linux | python-build-standalone(indygreg) | gcc | .deb + tar.gz |
Linux dev 机可交叉编译 Windows 包(fsp b --target windows),反之亦然。
已知限制
missing 依赖误报导入名≠包名
fsp b 日志中 AST 发现未声明依赖 提示可能误报:当导入名与 PyPI 包名不一致时
(如 import yaml 对应包名 PyYAML、import PIL 对应 Pillow),即使 pyproject.toml
已正确声明依赖,missing 比较归一化包名仍会提示未声明。不影响打包功能(declared
优先下载),仅日志有误导性。
CI/CD 集成
fspack 可集成到其他 Python 项目的 CI/CD 工作流,实现自动打包与打包成功验证。提供两个可复用的 GitHub Actions workflow 模板:
templates/pack-check.yml— PR 验证打包(push/PR 触发,验证打包不破坏)templates/release-pack.yml— Release 发布安装包(tag 触发,矩阵打包 Windows + Linux 安装包附到 GitHub Release)
fspack 自身的发布流程
fspack 自身通过 .github/workflows/release.yml 在 git push v*.*.* 时用各平台原生 runner 打包自身发布到 GitHub Release:
| job | runner | 产物 |
|---|---|---|
pypi |
ubuntu-latest | sdist + wheel(uv build → uv publish) |
pack-windows |
windows-latest | NSIS 安装包 .exe + 跨平台便携包 .zip |
pack-linux |
ubuntu-latest | tar.gz 便携包 + .deb 安装包 + 跨平台便携包 .zip |
release |
ubuntu-latest | 收集以上产物统一上传到 GitHub Release |
原生平台打包使 pyc 预编译生效、loader 用本机 gcc/mingw 原生编译,避免交叉编译的 wine 不稳定。任一 job 失败时 release 仍尝试发布已成功产物,但最终标记 workflow 失败。
快速上手
-
复制模板到你的项目:
cp templates/pack-check.yml your-project/.github/workflows/ cp templates/release-pack.yml your-project/.github/workflows/
-
在仓库 Settings → Secrets and variables → Actions → Variables 配置:
变量名 必填 说明 示例值 PROJECT_NAME是 项目名(与 pyproject.toml的name一致)my_appEXPECTED_OUTPUT是 运行打包后 exe 应输出的预期字符串 hello from my_appENTRY_NAMES否 多入口项目入口名列表(逗号分隔),未设置时按单入口处理 cli,gui,web -
触发:push 到 main 验证打包,打 tag(
git tag v0.1.0)发布安装包。
测试打包成功的三层反馈
| 阶段 | 成功反馈 | 失败反馈 |
|---|---|---|
| 构建 | fsp b 退出码 0 + 产物断言通过 |
退出码非零,上传 dist/ 供调试 |
| 运行 | grep 命中预期字符串 | grep 失败,输出实际内容到日志 |
| 安装包 | 文件存在 + 魔数校验(MZ/!<arch>/gzip) |
文件缺失或魔数错误 |
完整集成方案见 CI/CD 集成指南。
开发
# 安装开发依赖
uv sync --extra dev
# 运行测试(含覆盖率,阈值 95%)
uv run pytest -m "not slow" --cov=fspack --cov-fail-under=95
# 类型检查
uv run pyrefly check
# 代码风格
uv run ruff check src tests
uv run ruff format --check src tests
Make 快捷命令
项目提供 Makefile 封装常用操作,运行 make help 查看全部命令:
make sync # 安装开发依赖
make check # 全套门禁 (lint + typecheck + cov)
make build # 构建分发包
make clean # 清理构建产物
make bump PART=patch # 版本号 bump
文档
文档由 Sphinx 构建,托管在 ReadTheDocs:
make doc
多版本测试
使用 tox 在多个 Python 版本(py38, py39, py310, py311, py312, py313, py314)下运行测试:
make tox
许可证
MIT
Release files for fspack 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fspack-0.2.5.tar.gz | 519.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fspack-0.2.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 707.6 kB
Release files / fspack-0.2.5.tar.gz
| Download URL | fspack-0.2.5.tar.gz |
|---|---|
| Size | 519.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9238b9776b47f70dec4dc5a6f0666e713c9f5b87d0b6afa90610cfbebe18e047
|
|
BLAKE2b-256 checksum How to use checksums |
a33ef42c5419674bc6de6b3e8164d94ac6309b58ef9b734f2cfbc36b6a29ae5c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fspack-0.2.5-py3-none-any.whl
| Download URL | fspack-0.2.5-py3-none-any.whl |
|---|---|
| Size | 187.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6630767dd76eff88bbd76997f436b23fe0d59e56f5cda5ec5fe1959412891236
|
|
BLAKE2b-256 checksum How to use checksums |
d5d0cf7316e9f0a46f18d451b2f91886e6827bca24a14d1db38dd7fbbde9359a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|