
本文介绍一种兼容 Poetry 2.0 和 uv 的标准化方案:利用 PEP-621 定义的 project.optional-dependencies 表,在单个 pyproject.toml 中声明 dev 依赖,实现双工具同步安装与锁文件生成,无需重复配置。
本文介绍一种兼容 poetry 2.0 和 uv 的标准化方案:利用 pep-621 定义的 `project.optional-dependencies` 表,在单个 `pyproject.toml` 中声明 dev 依赖,实现双工具同步安装与锁文件生成,无需重复配置。
在现代 Python 项目中,越来越多团队希望逐步迁移到更轻量、更快的依赖管理工具(如 uv),同时又不能立即弃用仍被 CI/CD 或部分开发者广泛使用的 poetry。幸运的是,Poetry 2.0 已全面支持 PEP-621,即通过标准 [project] 表定义核心元数据(如名称、版本、依赖等)。但一个关键痛点在于:开发依赖(dev dependencies)尚未实现跨工具语义对齐。
Poetry 原生使用 [tool.poetry.group.dev.dependencies],而 uv(及 PEP-735 提案)倾向采用 [dependency-groups]。目前 Poetry 尚未原生支持 dependency-groups(相关 issue:python-poetry/poetry#9751),因此直接混用会导致 poetry lock 忽略 dependency-groups.dev,造成依赖缺失。
✅ 推荐解法:复用 project.optional-dependencies
这是当前最简洁、标准且双向兼容的方案——将开发依赖注册为可选依赖组:
[project] name = "my-awesome-package" version = "0.1.0" requires-python = ">=3.9" dependencies = [ "requests >=2.28", ] [project.optional-dependencies] dev = [ "bandit ~= 1.8.3", "black ==24.4.2", "pytest >=7.0", "mypy >=1.10", ]
该配置完全符合 PEP-621,被 Poetry 2.0 和 uv 均原生识别:
| 工具 | 同步 dev 依赖命令 | 锁文件影响 |
|---|---|---|
| Poetry | poetry sync --extras dev |
✅ 自动包含于 poetry.lock
|
poetry sync --all-extras |
✅ 同步全部可选组 | |
| uv | uv sync --extra dev |
✅ 生成 uv.lock 并解析 dev 组 |
uv sync --all-extras |
✅ 等效于 --extra dev + 其他组 |
? 提示:
uv sync --extra dev默认仅安装dev组及其传递依赖;若需同时安装主依赖 + dev 依赖,请确保project.dependencies已正确定义(uv会自动合并主依赖与指定 extras)。
⚠️ 注意事项与权衡
-
语义差异:
optional-dependencies在语义上表示“用户可选安装的功能扩展”,而非严格意义上的“仅用于开发”。这意味着:- 该组会出现在包的 PyPI 元数据中;
- 用户可通过
pip install mypackage[dev]直接安装(虽非典型用法,但技术上可行); - 若项目计划发布到 PyPI,需确认是否接受此公开暴露。
-
不适用于私有/纯 CI 工具链:若某些工具(如
ruff,pre-commit)仅用于本地检查且绝不应被终端用户安装,建议将其移至pyproject.toml的工具专属段(如[tool.ruff]、[tool.pre-commit]),而非放入optional-dependencies。 -
避免重复声明:请勿同时保留
[tool.poetry.group.dev.dependencies]和[project.optional-dependencies.dev]—— Poetry 会优先读取tool.poetry段,导致optional-dependencies被忽略,破坏一致性。
✅ 总结
在 Poetry 2.0 与 uv 共存的过渡期,project.optional-dependencies 是现阶段最务实、最标准的 dev 依赖共用机制。它无需插件、不依赖未落地的 PEP-735,且能保证锁文件完整性与命令行为一致性。只要接受其“可选性”的公开语义,即可零成本实现双工具平滑协作——真正让 pyproject.toml 回归“单一事实源”(single source of truth)的本质。

















