pdm install 用于开发态依赖解析与安装,pdm sync 严格按 lock 文件还原环境以确保 CI/CD 可复现;直接 python main.py 会因未注入 pypackages 路径而报 ModuleNotFoundError,必须用 pdm run 执行。

直接用 pdm install 替代 pip install 不可行,pdm 的依赖管理逻辑和路径机制与 pip 完全不同;必须按 PEP 582 或虚拟环境双模式之一统一配置,否则 import 会失败、CI 会飘移、IDE 会报红。
为什么 python main.py 会报 ModuleNotFoundError?
不是包没装,是 Python 根本没看到它。pdm add requests 只改 pyproject.toml 和 pdm.lock,不落地安装;真正解压进磁盘的是 pdm install,且默认装到 __pypackages__/3.11/lib(路径含 Python 版本号)。系统 Python 的 sys.path 默认不含这个目录。
- ✅ 正确执行:用
pdm run python main.py—— 它自动把__pypackages__/3.11/lib插入sys.path[0] - ❌ 错误执行:直接
python main.py—— 绕过所有 pdm 路径注入,等同于裸 Python - 检查是否生效:
pdm run python -c "import sys; print(sys.path[0])",输出应含__pypackages__
如何让 pytest/mypy/black 这类工具正常工作?
它们是独立可执行文件,不会自动识别 __pypackages__,也不能靠改 PYTHONPATH 简单解决(因为 mypy 本身还要加载插件、类型 stubs)。
- 统一走
pdm run封装:pdm run pytest tests/、pdm run mypy src/ - 在
pyproject.toml的[tool.pdm.scripts]里定义别名,例如test = "pytest tests/",之后只需pdm run test - 若 black 已用
pdm add --dev black安装,直接pdm run black .即可调用,无需全局pip install black
pdm install 和 pdm sync 到底该用哪个?
二者行为差异极大,混用会导致本地环境和 CI 环境不一致。
立即学习“Python免费学习笔记(深入)”;
-
pdm install:读pyproject.toml+pdm.lock,做依赖解析(可能升级 minor/patch)、更新 lockfile、再安装 —— 适合开发态 -
pdm sync:跳过解析,严格按pdm.lock安装,不碰pyproject.toml,也不生成新 lock —— CI/CD 必选,确保构建可复现 - CI 中应禁用 editable 安装:
pdm sync --prod --no-editable,避免 dev 依赖污染生产镜像
Docker 镜像里怎么安全用 pdm?
容器内不推荐默认的 PEP 582 模式,因为多数基础镜像(如 python:3.11-slim)不带 __pypackages__ 支持,且 uwsgi/gunicorn 等 C 扩展依赖需要编译环境。
- 先关掉 PEP 582:
pdm config python.use_venv true,让 pdm 回退到标准虚拟环境模式 - Dockerfile 中用
RUN pdm install --prod --no-editable,而非pip install -r requirements.txt - 必须显式导出 PATH:
ENV PATH="/project/.venv/bin:$PATH",否则后续命令找不到gunicorn等可执行文件 - 如果坚持用 PEP 582(如极简无构建镜像),需手动注入:
ENV PYTHONPATH="/project/__pypackages__/3.11/lib",但兼容性风险高
最易被忽略的一点:pdm init 不会读取旧项目的 requirements.txt 或 setup.py,所有迁移必须手工补全 [project.dependencies] 并跑一次 pdm install,否则看似初始化成功,实际什么都没装上。


















