pyproject.toml:现代 Python 依赖管理
Source: Dev.to
介绍
pyproject.toml 是现代 Python 依赖管理背后的契约。
早期的项目依赖 setup.py 或者猜测构建需求,这导致构建脆弱且环境不可复现。本文分解关键的 PEP(518、517、621),并展示 pyproject.toml 如何与 python -m venv + python -m pip 结合,实现可预测的安装。
从可执行配置到静态元数据的转变
历史上,项目配置是以可执行的 Python 代码编写的。虽然灵活,但这种方式会产生副作用,并且使得静态分析变得困难,导致构建不可靠。
pyproject.toml 引入了一种静态的声明式格式,工具可以在不执行代码的情况下解析它。
构建系统声明
[build-system] 表告诉安装程序在构建项目之前需要哪些内容。
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
因为接口已标准化,pip 可以通过通用 API 与多个后端(setuptools、hatchling、flit、poetry‑core)一起工作。
项目元数据
[project] 表对名称、版本、依赖、作者等进行标准化——无需任何动态代码。
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-service"
version = "0.1.0"
description = "Internal API example"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.110",
"uvicorn[standard]>=0.29",
"pydantic>=2.7"
]
[project.optional-dependencies]
dev = [
"pytest>=8",
"ruff>=0.5",
"mypy>=1.10"
]
可选依赖
optional-dependencies 表允许您定义诸如 dev 的分组,可通过 pip install -e ".[dev]" 安装。
好处
| 区域 | pyproject.toml 的帮助方式 |
|---|---|
| 项目清晰度 | 所有元数据集中在一个可读的文件中。 |
| 可复现的安装 | 工具能够准确了解构建需求和受支持的 Python 版本。 |
| 可持续的依赖管理 | 集中的声明减少漂移,并使锁文件的生成变得直接。 |
常规工作流程
python -m venv .venv
source .venv/bin/activate
python -m pip install -e . # install in editable mode
python -m pip install -e ".[dev]" # install optional dev dependencies
在可编辑模式下,源代码的更改会即时生效,无需每次重新安装包。
常见陷阱
- 缺失或错误的
[build-system]– 构建失败或在不同机器上表现不一致。 - 重复的依赖声明(例如同时出现在
requirements.txt和pyproject.toml中)– 导致依赖漂移。 - 省略
requires-python– 包可能在不兼容的解释器上安装,运行时崩溃。 - 依赖宽松的版本范围且没有锁文件 – 会导致 CI 与本地环境之间的依赖图不同。
工具生态
| 工具 | 与 pyproject.toml 的关系 |
|---|---|
| venv | 简单的标准库解决方案;开箱即用。 |
| virtualenv | 提供更多选项,在某些情况下速度更快。 |
| poetry | 提供一个集成的工作流,用于依赖解析、发布以及锁文件管理,全部由 pyproject.toml 驱动。 |
所有这些都可以与 pyproject.toml 共存,它已成为 Python 打包的通用语言。
故障排除环境问题
如果环境在进行大量包实验后“莫名其妙”开始出错,问题往往出在环境状态而不是代码。重新从 pyproject.toml 创建虚拟环境通常比逐个修补不一致的安装更快。
- 陈旧环境 – 实验后留下的临时环境可能会导致导入混乱。工具(例如 KillPy)可以按年龄/大小扫描并列出陈旧环境,从而安全删除。
结论
pyproject.toml 并非昙花一现的潮流;它是 Python 环境和依赖管理的现代基石。为了实现真正的可复现性、降低团队摩擦并确保构建可预测,请将此文件置于工作流的核心位置。