返回专题首页

Python 专题

从本地代码到可复用工具:Python 包构建与发布入门

当一段代码开始在不同项目里重复出现时,把它做成一个真正可安装、可复用的 Python 包,往往比复制粘贴更值得。包化不仅是复用方式的升级,也是工程边界更清晰的一种表现。

Python 专题第 26 篇 / 39 篇4 分钟

当一段代码开始在不同项目里重复出现时,把它做成一个真正可安装、可复用的 Python 包,往往比复制粘贴更值得。包化不仅是复用方式的升级,也是工程边界更清晰的一种表现。

这一节我们会从构建产物、元信息、版本号、入口命令到发布流程,完整梳理一个 Python 包是如何从本地代码变成团队或社区可以消费的工具的。

为什么要把代码做成包?

复制粘贴当然很快,但它会把问题越积越多:

  • 修一个 bug 要改多个项目;
  • 版本不一致;
  • 没人知道哪份才是权威实现;
  • 复用关系全靠记忆。

而包化意味着你开始明确这段代码的边界:

  • 它对外暴露什么;
  • 它依赖什么;
  • 它如何被安装和升级;
  • 它的版本如何演进。

这比“代码复用”更进一步,因为它是在做真正的交付单元设计。

pyproject.toml 中的关键信息

现代 Python 包的元信息通常集中在 pyproject.toml 中。

这里面最关键的通常包括:

  • 包名;
  • 版本;
  • 描述信息;
  • Python 版本要求;
  • 运行依赖;
  • 可选开发依赖;
  • 构建后端。

也就是说,pyproject.toml 不只是一个配置文件,它几乎就是这个包的“身份证”。

别人要理解你的包是什么、怎么安装、依赖什么,很多时候第一眼看的就是这里。

构建产物:sdist 与 wheel

Python 包构建后,常见会生成两类产物:

  • sdist:源码分发包;
  • wheel:构建好的二进制分发格式。

你可以先把它们理解成:

  • sdist 更接近“原材料”;
  • wheel 更接近“可直接安装的成品”。

在大多数现代发布流程里,wheel 通常是更常被优先消费的形式,因为安装更快、更稳定。

理解这一层的意义,不是要求你自己手写所有构建细节,而是知道包发布并不是“把源码传上去”这么简单,它背后有标准化产物和分发流程。

版本号、入口命令与依赖声明

一个可复用包真正能被别人顺畅消费,至少要把三件事说清楚。

第一是版本号。版本号不是装饰,而是兼容性承诺的一部分。使用者会通过它判断能不能升级、升级后风险大不大。

第二是入口命令。如果你的包是 CLI 工具,那就需要明确安装后用户如何直接执行命令,而不是还要自己找模块路径。

第三是依赖声明。包依赖哪些第三方库,哪些是运行时必需,哪些是开发时才需要,都应该清楚表达。

换句话说,包发布不是“让代码能装”,而是“让代码被别人合理理解和使用”。

发布到私有源或 PyPI 的基本流程

从流程上看,包发布通常包括:

  • 确认元信息和版本;
  • 构建产物;
  • 本地安装验证;
  • 上传到目标源;
  • 在真实环境里按发布方式重新安装验证。

至于目标源是私有仓库还是公开 PyPI,取决于你的复用范围和分发策略。但不管发到哪里,关键都不是“传上去”,而是发布前后是否可验证、可回滚、可追踪。

包发布前的常见检查项

包发布最怕的不是“功能没写完”,而是“本地能用,发出去就坏”。

所以发布前至少应该检查:

  • 版本是否正确递增;
  • 依赖是否声明完整;
  • 入口命令是否正常;
  • 关键 API 是否稳定;
  • README 或使用说明是否跟当前版本一致。

这些检查的意义在于:包一旦发布,你就不只是对自己负责,而是在对外提供一个承诺。

总结与预告

这一节我们把“代码复用”从复制粘贴升级成了真正的包发布流程,理解了构建产物、版本号、依赖声明和发布渠道之间的关系。做成包之后,代码的边界和责任也会变得更加明确。

接下来我们会短暂停下来,集中处理一批 Python 开发里最容易踩到、也最值得提前理解的性能与行为陷阱。