PDM默认启用PEP 582模式,依赖安装至__pypackages__目录,通过pdm run注入路径实现隔离,不依赖虚拟环境;直接运行python main.py会失败,因未自动加载__pypackages__路径。

pdm 默认启用 PEP 582 模式,项目依赖直接装进 __pypackages__ 目录,不建虚拟环境也能隔离。这和 pipenv 或 poetry 的思路完全不同——它不是“换壳的 venv”,而是真正在 Python 导入机制层做文章:把 __pypackages__/X.Y/lib 插入 sys.path 开头,优先于系统 site-packages。
但这个机制有个硬前提:Python 解释器必须支持 -I(isolated)模式或通过 python -m pdm run 启动,否则 __pypackages__ 不会被自动识别。很多新手跑 python main.py 失败,就是因为没走 pdm run 这一层。
为什么 python main.py 找不到安装的包?
这是最常踩的坑:PDM 安装的包在 __pypackages__/3.11/lib 下,但直接调用系统 Python 时,sys.path 根本不含该路径。
-
pdm run python main.py✅ 自动注入__pypackages__路径 -
python main.py❌ 纯系统解释器,完全无视 PDM 项目结构 - IDE(如 VS Code、PyCharm)需手动配置解释器为
pdm python list返回的路径,再把__pypackages__/X.Y/lib加进PYTHONPATH或设为 Sources Root
pdm add 和 pdm install 的行为差异
pdm add 只写 pyproject.toml 并更新 pdm.lock,不实际安装;pdm install 才真正解压包到 __pypackages__。两者分离是 PEP 621 + lockfile 模式的标准做法,类似 npm install vs npm add。
-
pdm add requests→ 修改pyproject.toml中[project.dependencies],生成/更新pdm.lock -
pdm install→ 读pdm.lock,将锁定版本装入__pypackages__ -
pdm install --prod→ 跳过[project.optional-dependencies.dev],只装生产依赖 - CI 环境建议用
pdm sync替代install,它跳过解析,直接按 lockfile 安装,更快更确定
如何让非 PDM 命令(如 pytest、mypy)正常工作?
这些工具默认不走 pdm run,所以会找不到本地包或 dev 依赖。正确做法不是改 PATH,而是用 pdm run 包一层:
-
pdm run pytest tests/✅ 自动加载__pypackages__和 dev 依赖(如pytest) -
pdm run mypy src/✅ 同理 - 也可在
pyproject.toml的[tool.pdm.scripts]里定义别名:test = "pytest tests/",然后pdm run test - 注意:某些工具(如
black)若被pdm add --dev安装,它本身是可执行脚本,pdm run black .就能直接调用,无需全局安装
迁移老项目时 pdm init 容易忽略的关键点
对已有 requirements.txt 或 setup.py 的项目执行 pdm init,它不会自动导入依赖——只会生成空的 pyproject.toml。必须手动补全或用插件转换。
立即学习“Python免费学习笔记(深入)”;
-
pdm import requirements.txt✅ 支持标准格式,但不处理注释或条件行(如pkg; sys_platform == "win32") -
pdm import setup.py✅ 仅提取install_requires,忽略extras_require -
requires-python字段必须显式写进pyproject.toml,否则pdm python install不知道该装哪个 Python 版本 -
__pypackages__是 Git 未跟踪目录,首次pdm install后记得git add pyproject.toml pdm.lock,别漏了 lock 文件——它是复现环境的唯一依据
pdm run 或显式配置 PYTHONPATH,否则就断联。这点和 Node.js 的 node_modules 行为一致,但 Python 开发者习惯性直呼 python,反而最容易在这里卡住。


















