pdm 是当前事实标准的现代 python 包管理器,因其开箱即用、语义清晰、严格锁定,天然支持 pep 621/665 和多环境隔离,可复现、可审计、ci 友好且无隐式依赖污染。

pdm 是目前最接近「开箱即用 + 语义清晰 + 严格锁定」的现代 Python 包管理器,它天然支持 PEP 621(pyproject.toml 原生配置)、PEP 665(锁定文件标准化)和多环境隔离,比 pip + venv 更可靠,也比 conda 更轻量、更 Python-native。如果你需要的是**可复现、可审计、CI 友好、无隐式依赖污染**的开发环境,pdm 不是“可选”,而是当前事实标准。
为什么不用 pip install -r requirements.txt 搭建环境?
因为 requirements.txt 本质是运行时快照,不是声明式契约:
• 它不区分直接依赖与传递依赖,pip freeze > reqs.txt 会把 numpy 的 cython 依赖也写死,导致升级 numpy 时被意外锁死
• 它不记录 Python 版本约束,python_requires 信息丢失,CI 构建可能在 3.9 环境下拉取只兼容 3.11 的包
• 它无法表达可选依赖(如 [dev], [test]),最终要么全装、要么手动维护多份文件
• 它不生成符合 PEP 665 的 pd.lock 或 requirements.lock,无法满足金融/政企场景的 SBOM(软件物料清单)审计要求
pdm init 后必须手动改 pyproject.toml 的三个字段
pdm init 会生成基础 pyproject.toml,但以下三项不填等于放弃合规性:
requires-python = ">=3.11, :明确限定解释器范围,避免 CI 使用错误 Python 版本触发不可控行为-
dependencies = ["requests>=2.31.0"]:只写你代码直接 import 的包,不写任何子依赖;版本号必须带比较符(>=/~>),禁用==(除非有强理由,如安全补丁) -
dev-dependencies = { test = ["pytest>=7.4", "pytest-cov"], lint = ["ruff>=0.4"] }:用命名分组替代模糊的requirements-dev.txt,后续可通过pdm install -G test精确激活
pdm install 的默认行为其实不安全
执行 pdm install 默认只装 dependencies,不装 dev-dependencies —— 这对 CI 是对的,但对本地开发是错的。常见误操作:
- 运行
pytest报错ModuleNotFoundError: No module named 'pytest':忘了加-G test - 编辑器里
import pytest标红:因为 IDE 绑定的 Python 解释器是pdm创建的虚拟环境,但该环境没装 dev 组 -
pdm add pytest直接写进dependencies:这是最危险的,会把测试工具变成生产依赖,污染部署包
正确做法:
• 本地开发:用 pdm install -G test -G lint
• CI 流水线:用 pdm install --no-dev(确保只装 runtime 依赖)
• 部署镜像:用 pdm export -f requirements --without-hashes > requirements.txt(注意:仅用于兼容旧系统,非首选)
锁定文件 pdm.lock 必须提交到 Git,且禁止手改
pdm.lock 是 PEP 665 兼容的锁定文件,包含每个包的精确版本、哈希值、来源 URL 和依赖图。它的作用不是“让环境一致”,而是“证明本次构建可完全复现”:
- 每次
pdm add/pdm update后,pdm.lock自动更新,必须git add pdm.lock并提交 - CI 构建时应校验
pdm lock --check,失败即中止,防止有人绕过pdm直接 pip install - 如果手动修改
pdm.lock,pdm会在下次 install 时警告并拒绝使用,这是设计使然——锁定文件只应由工具生成 - 不要把它加入
.gitignore,也不要试图压缩或忽略哈希字段;它的体积大是合规性的代价
真正容易被忽略的点:团队协作时,有人用 pip install 装了包却没更新 pdm.lock,导致别人 pdm install 后行为不一致。解决办法只有两条:一是 CI 强制校验,二是本地 pre-commit hook 加 pdm lock --check。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











