Python Packaging (Deep Workflow)
Packaging connects source to installable artifacts. Prioritize reproducible builds, accurate dependencies, and safe automated releases.
When to Offer This Workflow
Trigger conditions:
- - New library or CLI; choosing among Poetry, Hatch, setuptools, uv, etc.
- Broken installs on some Python versions or platforms
- Publishing to PyPI or a private index from CI
Initial offer:
Use six stages: (1) project layout, (2) metadata & entry points, (3) dependencies, (4) build backend & wheels, (5) versioning & tags, (6) publish & CI). Confirm supported Python versions and target index.
Stage 1: Project Layout
Goal: Prefer src/ layout to avoid accidental imports from the repo root; one clear import package name.
Exit condition: pip install . in a clean venv imports the package correctly.
Stage 2: Metadata & Entry Points
Goal: pyproject.toml with PEP 621 metadata; [project.scripts] or [project.gui-scripts] for CLIs.
Practices
- - Link README; specify license SPDX identifier
- Use classifiers for PyPI discoverability
Stage 3: Dependencies
Goal: Separate runtime deps from optional extras (dev, docs, speedups); pin strategy differs for libraries vs applications.
Libraries
- - Avoid overly tight upper bounds unless necessary (avoid dependency hell for consumers)
Applications
- - Use lockfiles (pip-tools, uv, poetry lock) for reproducible deploys
Stage 4: Build Backend & Wheels
Goal: Choose build backend (hatchling, setuptools, flit); emit wheel + sdist where appropriate.
Native extensions
- - Use cibuildwheel or similar for manylinux/macOS/windows matrices
Stage 5: Versioning & Tags
Goal: Single source of truth for version (static in pyproject or dynamic from VCS); git tags match releases.
Stage 6: Publish & CI
Goal: PyPI trusted publishing (OIDC) preferred over long-lived API tokens in secrets.
Practices
- - Test with TestPyPI when learning the flow
- Restrict token scope and enable 2FA on PyPI accounts
Final Review Checklist
- - [ ] src layout and imports verified in clean venv
- [ ] pyproject metadata complete; console scripts work
- [ ] Dependency policy documented (extras, bounds)
- [ ] Artifacts build for intended platforms
- [ ] Versioning aligned with tags; CI publishing secure
Tips for Effective Guidance
- - Add
py.typed for typed libraries (PEP 561). - Lazy-import heavy optional deps inside functions to keep CLI startup fast.
- Namespace packages are easy to misconfigure—prefer one clear top-level package name.
Handling Deviations
- - Monorepos: coordinate versions or use independent packages per folder with clear tooling.
- Docker-only apps: still package for testability; Dockerfile installs the wheel.
Python 打包(深度工作流)
打包将源代码与可安装制品连接起来。优先考虑可重现构建、精确的依赖关系和安全的自动化发布。
何时提供此工作流
触发条件:
- - 新库或 CLI;在 Poetry、Hatch、setuptools、uv 等工具间选择
- 在某些 Python 版本或平台上安装失败
- 从 CI 发布到 PyPI 或私有索引
初始提供:
使用六个阶段:(1) 项目布局,(2) 元数据与入口点,(3) 依赖关系,(4) 构建后端与 wheel 包,(5) 版本控制与标签,(6) 发布与 CI。确认支持的 Python 版本和目标索引。
阶段 1:项目布局
目标: 优先使用 src/ 布局,避免从仓库根目录意外导入;使用一个清晰的导入包名称。
退出条件: 在干净的虚拟环境中执行 pip install . 后能正确导入包。
阶段 2:元数据与入口点
目标: 使用符合 PEP 621 元数据的 pyproject.toml;CLI 使用 [project.scripts] 或 [project.gui-scripts]。
实践
- - 链接 README;指定许可证 SPDX 标识符
- 使用分类器提高 PyPI 可发现性
阶段 3:依赖关系
目标: 将运行时依赖与可选扩展(开发、文档、性能优化)分离;库与应用的版本锁定策略不同。
库
- - 除非必要,避免过于严格的上限约束(避免给使用者带来依赖地狱)
应用
- - 使用锁定文件(pip-tools、uv、poetry lock)实现可重现部署
阶段 4:构建后端与 Wheel 包
目标: 选择构建后端(hatchling、setuptools、flit);在适当情况下生成 wheel 包 + sdist 源码分发包。
原生扩展
- - 使用 cibuildwheel 或类似工具处理 manylinux/macOS/Windows 矩阵
阶段 5:版本控制与标签
目标: 单一版本来源(在 pyproject 中静态定义或从 VCS 动态获取);git 标签与发布版本匹配。
阶段 6:发布与 CI
目标: 优先使用 PyPI 可信发布(OIDC),而非在密钥中存储长期有效的 API 令牌。
实践
- - 学习流程时使用 TestPyPI 进行测试
- 限制令牌范围并在 PyPI 账户上启用双因素认证
最终审查清单
- - [ ] 在干净的虚拟环境中验证 src 布局和导入
- [ ] pyproject 元数据完整;控制台脚本正常工作
- [ ] 依赖策略已记录(扩展、边界)
- [ ] 为目标平台构建制品
- [ ] 版本控制与标签对齐;CI 发布安全
有效指导技巧
- - 为类型化库添加 py.typed(PEP 561)
- 在函数内部惰性导入重量级可选依赖,以保持 CLI 启动速度
- 命名空间包容易配置错误——优先使用一个清晰的顶级包名称
处理偏差
- - 单仓库:协调版本或按文件夹使用独立包并配备清晰工具
- 仅 Docker 应用:仍需打包以确保可测试性;Dockerfile 安装 wheel 包