Python 高阶编程技术 · 第 7 篇
现代打包、发布与依赖管理
(适配 Python 3.12;示例覆盖 Linux/macOS/Windows × x86_64/arm64)
──────────────────
- 引言
“代码能跑”只是开始,真正的价值在于“能被复用、能被安全分发、能在任何机器一键安装”。过去setup.py
+requirements.txt
的时代,我们被以下痛点支配:
• 引入一个 C 扩展包即需编译环境,CI 挂、用户也挂;
• 多环境(prod/dev/test/benchmark)需求冲突,pip install -e .
塑料友情;
• 手动python setup.py sdist bdist_wheel && twine upload
,脚本漏签名,发布秒撤回。
PEP-517/518/621 重新定义了构建标准,pyproject.toml
成为单一真相;Poetry、Hatch、PDM 各显神通,pipx
、scikit-build-core
、maturin
把编译轮子一键托管。今天,我们将系统梳理现代 Python 打包生态:
- PEP-517 构建接口与后端选择;
- 依赖锁定、私有源、环境隔离策略;
- 多平台 wheel、代码签名、自动发布流水线。
读完即可把你的库从“能 pip”提升到“几乎零摩擦、三分钟全球可用”。
──────────────────
2. 原理剖析
2.1 PEP-517/518 与构建后端
• PEP-518:pyproject.toml [build-system]
声明构建依赖,安装前先解决。
• PEP-517:标准化 build_sdist
/ build_wheel
接口 → 工具(pip、build)可无视后端差异。
常见后端
后端 | 特色 | 适用 |
---|---|---|
setuptools.build | 传统+超兼容,支持 setup.cfg | 旧项目平滑迁移 |
hatchling | 纯表格配置,内置版本插件、自定义钩子 | 追求简洁/插件化 |
poetry-core | 与 Poetry 生态深度集成 | 应用/库二合一 |
2.2 PEP-621:项目元数据表格化
[project] name/version/dependencies
统一,不再混写代码。IDE → 语义化解析,安全扫描更简单。
2.3 Wheel 格式与平台标签
• py3-none-any.whl
:纯 Python;
• cp312-cp312-macosx_14_0_arm64.whl
:ABI、平台双限定;
• manylinux / musllinux 为 Linux 二进制统一 ABI;auditwheel
/ delocate
修剪 & 打包共享库。
2.4 依赖管理策略
• 主依赖:用户运行所需 → [project] dependencies
;
• 可选特性:[project.optional-dependencies] svg = ["cairosvg"]
;
• 开发环境:Poetry [tool.poetry.group.dev]
; Hatch envs.dev.dependencies
;
• 锁定文件:poetry.lock
、hatch.lock
;生产镜像 --no-root --only main
.
2.5 私有源与镜像
[[tool.poetry.source]] name="internal" url="https://pypi.xxx/simple" default=true
支持 BasicAuth、token、SSL pinning;Hatch 同理。
2.6 版本号 PEP-440 与语义化
1.2.3
正式;1.3.0rc1
候选;1.4.0.dev0
夜版。CI 以 Git tag / commit hash 动态注入(Hatch-version plugin)。
──────────────────
3. 代码实战(3 组示例)
3.1 用 Hatch 创建跨平台扩展包
$ hatch new fasthash && cd fasthash
pyproject.toml
关键段:
[build-system]
requires = ["hatchling>=1.24", "hatch-vcs"] # 基于 Git tag 注入版本
build-backend = "hatchling.build"
[project]
name = "fasthash"
dynamic = ["version"] # 交给 hatch-vcs
requires-python = ">=3.9"
dependencies = ["typing-extensions"]
[tool.hatch.build.targets.wheel]
packages = ["fasthash"]
目录结构
fasthash/
__init__.py # __all__, __version__
core.pyx # Cython 扩展
增加插件 hatch-build-cython
,hatch build -t wheel
即生成多平台 wheel;本地测试:pipx run build && pip install dist/*.whl
.
3.2 Poetry 管理多环境依赖 + 私有源
poetry init -n
poetry add fastapi pydantic@^2.6
poetry add -G "svg" cairosvg==2.* # 可选
poetry add --group test pytest pytest-cov
poetry config repositories.internal https://pypi.int/simple
poetry add --source internal internal-lib@^0.5
激活不同 profile
poetry install --with test,svg # dev 环境
poetry install --only main # 生产镜像
3.3 GitHub Actions – 构建+签名+发布
.github/workflows/release.yml
(精简)
name: Build & Release
on:
push:
tags: ["v*.*.*"]
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
python: ["3.12"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: ${{ matrix.python }}}
- run: pip install hatch hatchling hatch-vcs
- name: Build wheel
run: hatch build -t wheel
- name: Sign wheel
run: |
for f in dist/*.whl; do gpg --detach-sign -a "$f"; done
- uses: actions/upload-artifact@v4
with: {path: dist/*}
publish:
needs: build
runs-on: ubuntu-latest
environment: pypi
steps:
- uses: actions/download-artifact@v4
- name: Publish
run: |
pip install twine
twine upload --sign --identity 'ABCD1234' dist/*
env:
TWINE_USERNAME: "__token__"
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
- name: GH Release
uses: softprops/action-gh-release@v2
with:
files: dist/*
• Matrix 自动生成 mac(x86+arm)/linux/musl/win 轮子;
• gpg --detach-sign
满足 PEP-480 完整性;
• 成功后将同一套文件推送至 PyPI & GitHub Releases。
──────────────────
4. 常见陷阱 & 最佳实践
陷阱
setup.py install
仍被调用:确保项目根 没有 裸setup.py
;- 忘记
include = ["*.pyx"]
,sdist 缺源码导致重建失败; - 多平台编译非法依赖系统 lib(glibc 版本老)→ manylinux audit 失败;
- Private source 未设置
default = true
,pip 回落官方源下载错包; - GPG 缺失
--armor
→ Twine 无法识别签名。
最佳实践
✓ 生成 sdist
+ wheel
双份,确保源码可重建;
✓ 使用 build --no-isolation
于 CI 复现环境,加 -C--editable
作为早期体验;
✓ 版本号 = Git tag,CI 拒绝脏树;
✓ 配置 pip.conf
全局缓存私有源,加速 CI;
✓ Mac + Linux arm64 需交叉编译或自托管 runner,提前拉好 SDK;
✓ 发布前 twine check dist/*
+ pip install --no-index --find-links dist/ pkg
.
──────────────────
5. 延伸阅读 / 练习
阅读
• PEP-639 – 二进制元数据文件签名;
• Hatch 文档 “Publishing Workflows & Hooks”;
• Poetry Plugin poetry-dynamic-versioning
。
练习
- 用
scikit-build-core
把 CMake 项目(含 C++)包装为 wheel,并走 manylinux。 - 编写一个 Hatch hook:自动把
README.md
副语言翻译产物注入 sdist。 - 修改上方 CI,使 release 过程生成 SBOM(cyclonedx-python-lib)。
──────────────────
6. 小结(Key Takeaways)
• PEP-517/518 把“如何构建”与“用什么工具”解耦,pyproject.toml
成为单一声明源。
• Hatch/Poetry/PDM 以表格元数据 + 锁文件解决多环境依赖与复现。
• Wheel 是首选发布格式;manylinux/delocate 保证二进制可移植。
• 私有源、分组依赖、语义化版本让应用与库共存无痛。
• GitHub Actions 可矩阵生成多平台 wheel → GPG 签名 → 一键推送 PyPI & Releases,实现全自动、可回滚、安全可审计的发布链。
下一篇《测试驱动开发与持续集成——pytest 深度实践》见!
发布者:admin,转转请注明出处:http://www.yc00.com/web/1754416164a5156808.html
评论列表(0条)