Stanley Ulili 2025-03-12
PDM 是一个现代化的 Python 包和依赖管理工具,强调对 PEP 标准的合规性以及开发者体验。
它旨在将其他语言生态中的最佳实践引入 Python,提供一种更直观、高效的项目与依赖管理方式。
本文将为你介绍 PDM,解释其核心概念与优势,并指导你如何在 Python 开发工作流中实施 PDM 的最佳实践。
前提条件
要跟随本教程操作,你需要在系统上安装较新版本的 Python(推荐使用 Python 3.13 或更高版本)。虽然 PDM 可以帮助管理多个 Python 版本,但至少拥有一个已安装的 Python 解释器会让入门过程更加简单。
为什么要使用 PDM?
在深入了解 PDM 之前,我们先了解它相比传统 Python 项目管理方法有哪些显著改进。以下是 PDM 的独特之处:
- PEP-621 兼容的项目管理:PDM 完全支持官方 Python 打包标准,使用
pyproject.toml作为项目配置的唯一真实来源。 - 虚拟环境自动化:PDM 自动为你的项目创建并管理隔离环境,无需显式激活。
- 确定性的依赖解析:PDM 通过其高级依赖解析器和锁文件机制,确保构建结果可复现。
- 强大的插件系统:PDM 支持插件扩展,允许你根据具体项目需求自定义和增强工作流。
你可以将 PDM 理解为 pip、virtualenv 和 poetry 的融合体——一个统一的、遵循现代 Python 标准的包管理和工作流工具。
安装 PDM
本节将指导你在本地机器上安装 PDM。
在 Linux 上,推荐使用官方安装脚本进行安装(在 macOS 上,你也可以通过 Homebrew 轻松安装):
curl -sSL https://pdm-project.org/install-pdm.py | python3 -
安装程序会将 PDM 安装到 $HOME/.local/bin 目录下。
请确保该路径已加入你的 PATH 环境变量。将以下行添加到你的 shell 配置文件中(如 .bashrc、.zshrc 或 .profile):
export PATH="$HOME/.local/bin:$PATH"
然后应用更改:
source ~/.bashrc
验证 PDM 是否成功安装:
pdm --version
输出示例:
PDM, version 2.22.4
这表明 PDM 已成功安装并可正常使用。
快速上手 PDM
现在 PDM 已安装完毕,让我们探索它的核心功能。PDM 通过自动管理虚拟环境和依赖安装,同时严格遵循现代 Python 打包标准,简化了 Python 项目管理。
要使用 PDM 创建一个新项目,请先创建项目目录并进入:
mkdir pdm-demo && cd pdm-demo
初始化一个新的 PDM 项目:
pdm init
该命令会启动交互式设置流程,提示你配置关键项目信息,例如 Python 解释器、项目名称、版本、许可证、作者信息和依赖项:
Creating a pyproject.toml for PDM...
Please enter the Python interpreter to use
0. cpython@3.13 (/opt/homebrew/bin/python3)
1. cpython@3.13 (/opt/homebrew/bin/python3.13)
2. cpython@3.12 (/opt/homebrew/bin/python3.12)
3. cpython@3.9 (/usr/bin/python3)
4. cpython@3.13 (/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/bin/python3.13)
Please select (0): 1
Virtualenv is created successfully at /Users/stanley/pdm-demo/.venv
Project name (pdm-demo):
Project version (0.1.0):
Do you want to build this project for distribution(such as wheel)?
If yes, it will be installed by default when running `pdm install`. [y/n] (n):
License(SPDX name) (MIT):
Author name (Your name):
Author email (youremail@gmail.com):
Python requires('*' to allow any) (==3.13.*):
Project is initialized successfully
完成后,PDM 会生成一个 pyproject.toml 文件,其中包含项目的元数据和配置。
该文件是项目的中心描述文件,用于定义依赖项、打包设置及其他相关信息。
与传统工作流需要手动创建并激活虚拟环境不同,PDM 自动完成这一过程,大大简化了项目初始化。
要安装一个包,只需运行:
pdm add requests
输出示例:
Adding packages to default dependencies: requests
0:00:03 🔒 Lock successful.
Changes are written to pyproject.toml.
Synchronizing working set with resolved packages: 5 to add, 0 to update, 0 to remove
✔ Install idna 3.10 successful
✔ Install certifi 2025.1.31 successful
✔ Install requests 2.32.3 successful
✔ Install urllib3 2.3.0 successful
✔ Install charset-normalizer 3.4.1 successful
0:00:01 🎉 All complete! 5/5
安装过程中,如果尚不存在虚拟环境,PDM 会自动创建;随后安装该包及其依赖,并更新 pyproject.toml 和 pdm.lock 以跟踪依赖关系。
你也可以一次安装多个包:
pdm add numpy pandas matplotlib
或指定版本约束:
pdm add "django>=4.2"
如前所述,PDM 的一大特点是无需手动激活虚拟环境。要测试安装是否成功,可创建一个简单的 Python 脚本:
app.py
import requests
response = requests.get("https://api.github.com/users/pdm-project")
data = response.json()
print(f"PDM GitHub repository: {data['html_url']}")
print(f"PDM has {data['public_repos']} public repositories")
使用 PDM 运行它:
pdm run python app.py
输出示例:
PDM GitHub repository: https://github.com/pdm-project
PDM has 19 public repositories
这会自动使用正确的虚拟环境,让你轻松处理多个项目而不会出现环境冲突。
至此,你已经看到 PDM 如何简化依赖管理和项目设置。它消除了传统工具所需的许多手动步骤,同时确保项目遵循现代 Python 最佳实践。
使用 PDM 管理依赖
现在,让我们深入探讨 PDM 强大的依赖管理能力,它使包安装、版本控制和环境同步更加可靠。
PDM 的依赖管理基于两个关键文件:
pyproject.toml:声明项目的依赖项及其版本规范pdm.lock:记录所有依赖项及子依赖项的确切版本
当你使用 PDM 添加包时,它会自动更新这两个文件:
pdm add fastapi
该命令会安装 FastAPI 并更新项目配置:
pyproject.toml
[project]
name = "pdm-demo"
version = "0.1.0"
description = ""
authors = [
{name = "Your Name", email = "your.email@example.com"},
]
dependencies = ["requests>=2.32.3", ..., "fastapi>=0.115.11"]
requires-python = "==3.13.*"
readme = "README.md"
license = {text = "MIT"}
[tool.pdm]
distribution = false
同时,PDM 还会创建一个详细的锁文件,精确记录 FastAPI 及其所有子依赖的版本。这确保了其他协作者能获得完全相同的开发环境。
PDM 提供对版本约束的精细控制。例如:
pdm add "sqlalchemy>=2.0.0" "pydantic<2.0.0"
这会添加 SQLAlchemy(最低版本 2.0.0)和 Pydantic(最高版本低于 2.0.0)。
要将依赖更新到最新兼容版本:
pdm update
或仅更新特定包:
pdm update fastapi pydantic
如果不再需要某个包,可将其移除:
pdm remove fastapi
这不仅会卸载该包,还会同步更新 pyproject.toml 和 pdm.lock,确保依赖声明与实际安装保持一致。
在团队协作或在新机器上设置项目时,你无需逐个安装包。只需克隆包含 pyproject.toml 和 pdm.lock 的仓库,然后运行:
pdm install
这会安装锁文件中指定的确切版本,确保所有开发机和部署目标环境的一致性。
PDM 还能让你轻松在项目环境中运行命令而无需激活环境:
pdm run python -c "import requests; print(requests.__version__)"
输出示例:
2.32.3
使用 PDM 的现代化依赖管理方法有助于在开发、测试和生产环境中保持一致性,减少 Python 项目中常见的兼容性问题。
使用 PDM 的依赖分组功能
大多数 Python 项目在不同场景下需要不同的依赖集。PDM 通过依赖分组(dependency groups)提供了清晰的解决方案,让你能根据用途对依赖进行分类管理。
依赖分组具有以下优势:
- 清晰区分运行时依赖和开发依赖
- 能够只为特定任务安装所需依赖
- 改善项目组织结构和文档说明
- 减少生产环境中的依赖体积
如前所述,使用 pdm add 添加的包会进入 pyproject.toml 的主依赖部分:
pdm add sqlalchemy
结果如下:
pyproject.toml
[project]
dependencies = [
"sqlalchemy>=2.0.39",
]
然而,仅在开发过程中使用的工具(如测试框架、类型检查器或代码格式化工具)应单独存放。PDM 通过 --dev 或 -d 标志轻松实现这一点:
pdm add --dev pytest mypy black
这会创建一个名为 "dev" 的可选依赖分组:
pyproject.toml
...
[dependency-groups]
dev = [
"pytest>=8.3.5",
"mypy>=1.15.0",
"black>=25.1.0",
]
开发依赖不会包含在你的包分发元数据中,非常适合仅在开发阶段使用的工具。
你可以创建多个开发依赖分组:
pdm add -dG test pytest pytest-cov
pdm add -dG lint flake8 black
结果如下:
pyproject.toml
...
[dependency-groups]
...
test = [
"pytest>=8.3.5",
"pytest-cov>=6.0.0",
]
lint = [
"flake8>=7.1.2",
"black>=25.1.0",
]
对于应包含在包元数据中的依赖(如可选功能),请使用 -G/--group 选项:
pdm add -G web flask jinja2
这会将依赖添加到可选依赖部分:
pyproject.toml
...
[project.optional-dependencies]
web = [
"flask>=3.1.0",
"jinja2>=3.1.6",
]
...
使用特定分组中的依赖
要使用特定分组中的包运行命令,请使用 pdm run。例如,执行开发依赖中的包:
pdm run pytest
输出示例:
============================================================== test session starts ==============================================================
platform darwin -- Python 3.13.2, pytest-8.3.5, pluggy-1.5.0
rootdir: /Users/stanley/pdm-demo
configfile: pyproject.toml
plugins: cov-6.0.0
collected 0 items
============================================================= no tests ran in 0.01s =============================================================
要选择性地安装依赖,请使用相应的 pdm install 命令:
仅安装生产依赖:
pdm install --prod安装生产依赖及特定可选分组:
pdm install -G web
不同命令组合会安装不同的依赖集:
pdm install:安装生产依赖 + 所有开发依赖pdm install -G web:安装生产依赖 + "web" 可选分组 + 所有开发依赖pdm install -G test:安装生产依赖 + 仅 "test" 开发分组pdm install --prod:仅安装生产依赖
通过 PDM 将依赖组织成逻辑分组,可以提升项目的可维护性,明确定义包的用途,并为特定任务优化环境。
使用 PDM 管理 Python 版本
在不同项目间管理 Python 版本是开发者常遇到的挑战。PDM 通过内置的 Python 版本管理功能简化了这一过程,确保你的项目始终使用正确的 Python 版本。
PDM 的 Python 版本管理基于两个核心概念:
- 在
pyproject.toml中声明 Python 版本要求 - 根据这些要求自动选择合适的 Python 解释器
初始化 PDM 项目时,你需要指定 Python 版本要求:
pyproject.toml
[project]
requires-python = "==3.13.*"
此示例表示项目兼容任意 3.13.x 版本。创建新项目时,PDM 会根据你选择的 Python 版本建议默认值。
PDM 会自动从系统中可用的 Python 解释器中选择合适的一个。要查看 PDM 当前为项目使用的 Python 版本:
pdm info
输出示例:
PDM version:
2.22.4
Python Interpreter:
/Users/stanley/pdm-demo/.venv/bin/python (3.13)
Project Root:
/Users/stanley/pdm-demo
Local Packages:
如果你需要使用不同的 Python 版本,请确保它与项目 requires-python 规范兼容。
例如,若尝试将要求 ==3.13.* 的项目切换到 Python 3.12:
pdm use python3.12
输出:
[NoPythonVersion]: No Python interpreter matching requires-python="==3.13.*" is found.
要成功切换 Python 版本,请先更新 pyproject.toml 中的 requires-python 值为 >=3.12:
pyproject.toml
[project]
name = "pdm-demo"
version = "0.1.0"
...
requires-python = ">=3.12"
....
然后切换 Python 版本:
pdm use python3.12
输出:
INFO: Using the first matched interpreter.
Virtualenv is created successfully at /Users/stanley/pdm-demo/.venv
Using Python interpreter: /Users/stanley/pdm-demo/.venv/bin/python
(3.12)
这确保了你的项目依赖与所用 Python 版本保持兼容。
使用 PDM 安装 Python 版本
PDM 的一个重要特性是能够直接安装不同的 Python 版本。
要查看所有可安装的 Python 版本:
pdm python install --list
输出示例:
cpython@3.13.2
cpython@3.13.1
cpython@3.13.0
cpython@3.12.9
cpython@3.12.8
cpython@3.12.7
...
cpython@3.11.11
cpython@3.11.10
cpython@3.10.4
cpython@3.10.3
cpython@3.8.13
cpython@3.8.12
pypy@3.11.11
pypy@3.10.19
pypy@3.10.14
...
pypy@3.9.15
pypy@3.8.16
pypy@3.8.15
PDM 还能根据项目的 requires-python 自动选择最佳 Python 版本。例如,自动安装并使用最高兼容版本:
pdm python install
或安装最低兼容版本:
pdm python install --min
这些功能使 PDM 成为高效管理 Python 环境的便捷工具。
总结
本文探讨了 PDM 的关键特性,帮助你现代化 Python 开发工作流。PDM 将现代依赖管理、项目结构和 Python 版本处理整合到一个符合标准的单一工具中。
欲了解更多信息,请访问 PDM 官方文档。