【Python高阶编程技术】第7篇 现代打包、发布与依赖管理

Python 高阶编程技术 · 第 7 篇现代打包、发布与依赖管理(适配 Python 3.12;示例覆盖 LinuxmacOSWindows × x86_64arm64&#xf

Python 高阶编程技术 · 第 7 篇

现代打包、发布与依赖管理
(适配 Python 3.12;示例覆盖 Linux/macOS/Windows × x86_64/arm64)

──────────────────

  1. 引言
    “代码能跑”只是开始,真正的价值在于“能被复用、能被安全分发、能在任何机器一键安装”。过去 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 各显神通,pipxscikit-build-corematurin 把编译轮子一键托管。今天,我们将系统梳理现代 Python 打包生态

  1. PEP-517 构建接口与后端选择;
  2. 依赖锁定、私有源、环境隔离策略;
  3. 多平台 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.lockhatch.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-cythonhatch 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. 常见陷阱 & 最佳实践

陷阱

  1. setup.py install 仍被调用:确保项目根 没有setup.py
  2. 忘记 include = ["*.pyx"],sdist 缺源码导致重建失败;
  3. 多平台编译非法依赖系统 lib(glibc 版本老)→ manylinux audit 失败;
  4. Private source 未设置 default = true,pip 回落官方源下载错包;
  5. 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

练习

  1. scikit-build-core 把 CMake 项目(含 C++)包装为 wheel,并走 manylinux。
  2. 编写一个 Hatch hook:自动把 README.md 副语言翻译产物注入 sdist。
  3. 修改上方 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信