Poetry 2 工程手册:依赖锁定、环境隔离与发布边界
Poetry 经常被一句“Python 依赖管理工具”带过,于是团队只记住 poetry install。真正进入多人协作后,问题很快变成:项目是应用还是可发布包,元数据写在 PEP 621 还是旧表中,锁文件由谁更新,开发依赖是否进入生产,私有包从哪个源解析,Poetry 自己的插件又运行在哪个环境。
Poetry 的工程价值是把项目意图、解析结果、环境入口和构建发布命令收敛到一个可版本化控制面。它不能消除平台 wheel、原生编译、私有源、凭证和供应链风险;架构师仍要为这些边界建立证据与停止条件。
先判断项目是否需要 Poetry
当团队希望用一个项目入口统一管理 pyproject.toml、依赖解析、锁文件、虚拟环境、依赖组和 Python 包构建时,Poetry 能明显降低成员之间的工具差异。若仓库只需要轻量安装 requirements,pip 与 venv 可能更直接;若还要统一 Python 下载、跨语言任务或大规模 workspace,则应比较 uv 或更上层的工程工具。
Poetry 管理的是 Python 项目依赖与打包控制面,不负责 Python 解释器的补丁生命周期,也不部署 PyPI 或私有制品库服务端。应用发布、容器运行和生产运维仍由交付流水线负责,不能因为使用 poetry publish 就把权限和职责合并。
接手项目时先查清三套环境
准备受支持的 Python、一台非生产机器和可删除的练习目录。先记录:
python --version
poetry --version
poetry debug info若 Poetry 尚未安装,poetry --version 失败是正常现象。此时先确认安装来源和目标版本,不要把 Poetry 安装进它随后要管理的项目环境。
安装入口与卸载边界
安装前先打开 Poetry 稳定版安装说明,确认当前稳定分支、系统要求和目标版本。Poetry 2.4 要求 Python 3.10+;运行 Poetry 的 Python 与项目声明支持的 Python 是两项独立约束,不能用其中一个替代另一个。
pipx:开发机首选之一
pipx 会为 Poetry 建立独立环境,并提供升级与卸载入口;这也是官方支持的安装路线之一:
pipx install "poetry==<approved-version>"
poetry --version升级和卸载分别使用:
pipx upgrade poetry
pipx uninstall poetry团队不应在文档里长期写“安装最新版”。开发机、CI 和故障复现都需要知道实际版本。升级动作先经过兼容验证,再更新批准版本。
官方安装器:先审脚本再执行
官方安装器支持 Linux、macOS、WSL 与 Windows PowerShell。生产化 CI 不建议直接把远程脚本流入解释器;先下载、校验、存入受控位置,再固定版本运行。
python3 install-poetry.py --version <approved-version>Windows 可使用下载后的脚本:
py .\install-poetry.py --version <approved-version>通过官方安装器安装时,可再次运行安装器并带 --uninstall 卸载。Windows 上官方文档提示 self update 可能有问题,重装往往更可控。
手动隔离环境:CI 控制力最高
python3 -m venv /opt/poetry
/opt/poetry/bin/python -m pip install "poetry==<approved-version>"
/opt/poetry/bin/poetry --version这个环境只放 Poetry 及其插件,不放项目依赖。Poetry 安装说明明确要求工具环境与目标项目环境隔离;若二者混装,项目解析可能升级或卸载 Poetry 自己的依赖,故障会表现为 Poetry 命令随机崩溃。
Poetry 管理的四层对象
pyproject.toml 表达意图
它同时承载标准项目元数据和 Poetry 专属配置。Poetry 2 的 pyproject.toml 说明推荐优先使用 PEP 621 的 [project] 元数据和 project.dependencies;旧的 [tool.poetry.dependencies] 仍用于 Poetry 专属扩展场景,不能把 Poetry 1 的配置示例原样当作新项目基线:
[project]
name = "demo-service"
version = "0.1.0"
requires-python = ">=3.12,<3.14"
dependencies = [
"httpx>=0.27,<1",
]
[build-system]
requires = ["poetry-core>=2.0"]
build-backend = "poetry.core.masonry.api"project.dependencies 是构建后会进入包元数据的运行依赖。Poetry 专属 source、复杂约束或兼容旧项目时,可能仍需 [tool.poetry] 补充,但每个重复声明都要说明所有权。
poetry.lock 固定解析结果
锁文件记录解析后的版本、文件和完整性信息。它应与 pyproject.toml 一起提交。poetry install 依据锁文件安装;当 manifest 与 lock 不一致时,应修复并评审 lock 变更,不要在 CI 静默重算。
虚拟环境承载物化结果
Poetry 可以复用已激活环境,也可以创建自己的环境。环境只是当前机器的物化结果,不提交、不复制,也不替代 lock。
cache 加速下载与制品处理
缓存不是依赖声明。排查源、证书和构建问题时要有冷缓存路径,CI cache key 必须包含 Poetry、Python、OS、架构和 lock hash。
package mode 与 non-package mode
Poetry 默认处于 package mode:当前项目本身可被构建、安装,必须具备包元数据。适合库、CLI 和需要将应用构建为 wheel/sdist 的项目。
纯应用仓库若只想管理依赖、不打包当前项目,可以使用:
[tool.poetry]
package-mode = falsenon-package mode 下,poetry install 不再尝试把当前项目安装成包,poetry build 与 poetry publish 也失去合理目标。它不是“少写几个字段”的临时修复,而是架构声明:该仓库只消费依赖,不产出 Python 包。
若项目代码依赖 editable 安装后的 entry point、包资源或导入布局,就不应为了绕过包结构错误而关闭 package mode。先确认交付物,再选择模式。
最小项目与首次验证
创建目录后,可以让 Poetry 初始化:
poetry init也可以手工创建前述 pyproject.toml,然后执行:
poetry check
poetry lock
poetry install
poetry env info
poetry run python -c "import sys, httpx; print(sys.executable); print(httpx.__version__)"poetry check 会检查配置并提示弃用字段;poetry lock 解析并写入锁;poetry install 物化环境;poetry run 明确在项目环境中执行。预期命令成功且解释器位于 Poetry 管理的环境。
验证清理与恢复:
poetry env remove --all
poetry install
poetry run python -m pytest只有删除环境后仍能从 pyproject.toml 与 poetry.lock 恢复,才证明项目契约成立。
环境位置与解释器选择
团队常把环境放在项目内,便于 IDE 发现:
poetry config virtualenvs.in-project true --local
poetry env use <approved-python-path>
poetry env info--local 配置会写入项目局部配置文件。提交前要判断它是否是团队契约,避免把个人绝对路径带入仓库。解释器选择应使用可追踪入口;只写 python3 可能在开发机和 runner 上解析到不同版本。
常用环境命令:
poetry env list --full-path
poetry env info --path
poetry run python --version
poetry env remove --all激活不是自动化前提。Poetry 2 的 shell 激活流程与旧教程可能不同,脚本和 CI 直接使用 poetry run 更稳定。
依赖、组与安装选择
添加运行依赖:
poetry add httpx添加开发组依赖:
poetry add --group dev pytest ruff组用于组织开发、测试、文档等依赖,不等同于发布包的 extras。新增组或调整安装选择前,应先核对 Poetry 依赖组说明。安装时可以选择:
poetry install --with dev
poetry install --without docs
poetry install --only main生产镜像通常只安装运行所需组,并关闭当前项目安装或保留它,取决于 package mode 与交付方式。不能机械复制 --no-root;它会跳过当前项目安装,可能让测试没有覆盖最终包布局。
依赖变更后审查:
poetry show --tree
poetry show --outdated
poetry check评审 lock diff 时关注直接与传递依赖、来源、hash、平台 marker 和包数量,不只看版本升降。
包源优先级与 dependency confusion
Poetry 包源说明把 source priority 分为 primary、supplemental 和 explicit。配置至少一个 primary source 会关闭隐式 PyPI;若仍需 PyPI,必须显式配置。
内部包最稳妥的方式之一,是把源设为 explicit 并给依赖绑定来源:
poetry source add --priority=explicit internal https://packages.example.invalid/simple/
poetry add --source internal internal-sdkexample.invalid 是保留示例域名。生成的配置会把包与 source 关联。注意来源约束不会自动继承给传递依赖;内部依赖的内部子依赖也要明确建模。
supplemental 只在更高优先级源没有兼容候选时查询,官方文档明确提醒:公有 primary 中出现同名包时,可能替代 supplemental 中的内部包。对仅应来自一个仓库的包,应使用 source constraint,并建立命名保留与审计。
代理、CA、权限与凭证
仓库只提交 source 名称、URL 和非敏感策略。认证配置使用 Poetry 的认证入口或环境变量,并由 secret manager 注入:
poetry config http-basic.internal <username> <token>命令仅说明入口,不应在共享终端直接填入真实 token,因为 shell 历史和进程信息可能泄露。CI 应使用受保护变量,令牌限定只读或发布权限,并在任务结束撤销或清理。
企业代理和私有 CA 需要统一安装到 runner 或 Poetry 可使用的信任链中。不要把关闭 TLS 校验当作长期方案。排障时记录 Poetry 配置来源、请求域名、代理层和证书颁发者,但日志必须脱敏。
锁文件更新与升级策略
修改依赖意图时使用 poetry add、poetry remove 或受控编辑后执行 poetry lock。只想确认 lock 与 manifest 一致,先运行 poetry check,不要在 CI 自动重写后继续构建。
升级应分三层:
Poetry CLI 版本。poetry-core 构建后端版本。项目依赖与 lock 内容。
三层同时升级会让失败无法归因。先固定旧证据,再一次改变一层,比较 lock diff、构建产物、依赖树、测试和环境恢复时间。
构建与发布边界
package mode 项目可以执行:
poetry build预期在 dist/ 生成 wheel 和 sdist。随后应在干净环境安装 wheel 并运行 smoke test,而不是只确认文件存在。
python -m venv verify-env
verify-env/bin/python -m pip install dist/*.whl
verify-env/bin/python -c "import demo_service"Windows 替换为 verify-env\Scripts\python.exe。发布命令需要仓库凭证,属于高权限动作:
poetry publish --repository <approved-repository>开发者日常安装依赖不应拥有生产发布 token。构建和发布应拆成不同流水线阶段,制品先扫描、签名或审批,再由短期凭证发布。
插件是 Poetry 自身的供应链
插件运行在 Poetry 进程内,可以改变命令与行为。全局插件可通过 poetry self add 管理;项目也可以在 [tool.poetry.requires-plugins] 声明所需插件,Poetry 2 会在项目下的 .poetry/plugins 处理缺失插件。
插件依赖可能与 Poetry 自身依赖冲突,Poetry 插件说明也提醒插件经常访问没有稳定公共 API 的内部实现。团队必须固定插件版本,纳入漏洞与许可证审查,并在 Poetry 升级兼容组合中单独验证。
poetry self show plugins故障排查时先列出插件,再用无插件基线复现。不要把插件造成的命令异常误判为项目 lock 损坏。
缓存与离线策略
查看和清理缓存应使用当前版本帮助确认命令:
poetry cache list
poetry cache clear --all <cache-name>清缓存是诊断动作,不是每次构建的默认步骤。真正的离线能力依赖内部包源或预先批准的 wheel 集合;仅复制 Poetry cache 缺乏稳定接口和来源审计,不应作为灾备方案。
CI cache key 至少包含 OS、架构、Python、Poetry 和 poetry.lock hash。缓存命中后仍运行 poetry check、安装和测试;定期安排冷缓存流水线发现隐式依赖。
CI 契约
流水线先安装固定 Poetry,再让项目根据 lock 恢复:
poetry --version
poetry check
poetry install --only main --no-interaction
poetry run python -m pytest是否使用 --no-root 取决于交付模型。库和依赖包布局的应用通常必须安装 root;纯依赖容器层或 non-package mode 项目才可能跳过。
合格 CI 还要记录 Python 与 Poetry 版本、lock hash、source 配置摘要和构建产物 hash。失败后保存脱敏日志,任务结束删除认证配置、临时环境和发布凭证。
常见失败:现象、判断与修复
poetry install 找不到当前项目包
判断项目是否应该处于 package mode,检查包目录与项目名映射。若本来就是可发布包,修正包布局;若只是依赖管理型应用,评审后使用 non-package mode。不要长期用 --no-root 掩盖错误模型。
lock 与 pyproject 不一致
先查看未提交变更和 Poetry 版本,再在受控分支执行 poetry lock,审查完整 diff。CI 应失败并要求提交修复,不应自动更新 lock。
本机成功、CI 找不到私有包
比较 source priority、依赖 source constraint、凭证注入和 CA。若本机用户配置提供了源而仓库没有,说明项目依赖隐式个人状态。把非敏感 source 契约纳入项目,把 secret 留在执行环境。
解析很慢
查看是否配置多个 primary 源、包元数据是否缺失、版本范围是否过宽。Poetry 可能下载分发文件检查元数据。优化源和约束,不能简单杀掉解析后提交旧 lock。
Poetry 命令自身崩溃
确认 Poetry 是否与项目共用环境,列出插件和安装来源。用同版本的干净独立 Poetry 环境复现;若恢复正常,重建工具环境,不要修改项目依赖迎合损坏的 CLI。
构建在某平台失败
区分 lock 解析成功与 native extension 构建失败。检查目标 Python ABI、wheel 可用性、系统头文件和构建后端。需要时在受控目标平台构建 wheel,不要把开发机生成的环境复制过去。
从 Poetry 1 或其他工具迁移
从 Poetry 1 升级时,先固定旧 Poetry 和旧 lock,运行测试与构建,保存依赖树。然后用 Poetry 2 的 poetry check 识别弃用字段,逐步迁移到 [project],不要同时大规模升级业务依赖。
从 requirements、pip-tools 或其他管理器迁入时,先提取直接依赖意图、Python 范围、source、hash 和平台 marker,再生成 Poetry 项目与 lock。原工具流水线继续保留,直到新旧双轨在代表性平台通过。
反向回滚要保留旧工具安装入口、旧 manifest/lock、旧 CI 镜像和旧发布流程。若 Poetry 2 迁移改变了包元数据或构建产物,必须比较 wheel 内容,不能只看测试绿色。
lock 不等于跨平台绝对一致
条件依赖、平台 marker、wheel 可用性和原生构建仍会让不同平台执行不同路径。验收标准是在批准的平台组合中冷恢复并通过测试,不是 lock 文件只有一份。
source priority 是安全设计
primary、supplemental、explicit 会改变候选集合和网络访问。内部包来源不明确时,dependency confusion 不是理论风险。所有仅内部提供的包都应有 source constraint 和命名责任人。
工具环境与项目环境必须分权
Poetry CLI、插件和项目依赖是三条供应链。它们共用环境时,一个普通依赖升级可能破坏构建工具。开发机和 CI 都应能独立重建 Poetry 工具环境。
发布权限不能跟着开发体验走
poetry publish 很方便,但便利不能让每位开发者持有生产发布 token。构建、审批、发布分离,令牌短期化、最小权限化,并保留审计和撤销路径。
插件放大长期维护成本
插件依赖 Poetry 内部 API,升级破坏面高于普通项目依赖。只有当插件消除稳定、重复的组织问题时才引入,并设置所有者、兼容组合和无插件回退路径。
Poetry CLI 与 poetry-core 均有批准版本,升级分层进行。Poetry 工具环境与项目环境彻底隔离。pyproject.toml 以 Poetry 2 / PEP 621 口径维护,弃用字段已审查。
package mode 或 non-package mode 有交付物依据。poetry.lock 提交且 CI 不自动重写。dependency groups 与生产安装选择有明确约定。
私有包使用 source constraint,source priority 经过安全评审。token、代理和 CA 由受管执行环境注入,日志脱敏。插件固定版本、指定所有者并纳入升级兼容组合。
CI 同时验证冷恢复、项目安装、测试和构建产物。package mode 项目在干净环境安装 wheel 做 smoke test。发布阶段与构建阶段分权,凭证可撤销、可审计。
迁移保留旧工具、旧 lock、旧镜像和双轨验证证据。故障能够区分 CLI、插件、解析、源、环境、构建和项目运行阶段。
当这些边界都能被仓库配置、流水线输出和责任人回答时,Poetry 才不只是一个顺手的命令入口,而是可升级、可回滚、可审计的 Python 项目控制面。
