在 Python 生态系统中,项目依赖管理一直是开发者面临的核心挑战之一。从最初的 pip
配合 requirements.txt
,到后来的 Pipenv
和 Poetry
,Python 社区一直在探索更高效、更可靠的解决方案。PDM (Python Development Master) 正是在这样的背景下应运而生的一款新一代 Python 包和依赖项管理器。它不仅继承了传统工具的优点,更引入了多项创新特性,旨在为 Python 开发者提供一个现代化、可靠且灵活的项目管理工作流程。
PDM 是一个遵循最新 PEP (Python Enhancement Proposals) 标准的 Python 包和依赖项管理器。它超越了简单的包安装功能,致力于在整个开发生命周期中提升效率和体验。PDM 的设计理念是提供一个轻量级、高性能且易于使用的工具,以应对日益复杂的 Python 项目依赖关系。
PDM 需要 Python 3.9 或更高版本才能运行。尽管 PDM 对 Python 版本有要求,但其管理的项目可以支持更低版本的 Python。PDM 的安装过程相对简单,并提供了多种安装方式以适应不同的开发环境和偏好。建议将 PDM 独立于应用程序安装成一个全局命令,以方便不同项目使用。本文仅演示一种个人倾向的安装方式,不代表最佳实践。
版本选择:支持 Python 3.9 的最新版。如下图所示,可以看到支持各个平台的安装包,这里选择 Miniconda3-py39_24.5.0-0-MacOSX-x86_64.sh
。详细的安装说明参见 这里。
激活一个 Python 3.9 的环境 (我这里是 conda activate py39
),然后依次执行如下命令
python -m pip install --user --upgrade pip
python -m pip install --user pipx
python -m pipx ensurepath
打开一个新的终端 Terminal, 测试是否安装成功
$ pipx --version
1.7.1
使用 pipx 安装 pdm 作为全局命令,以便在所有 Python 项目中方便使用。
pipx install pdm
测试是否安装成功
$ pdm --version
PDM, version 2.25.4
此外,再罗列一些相关命令
pipx list
查看通过 pipx 安装的全部全局命令pipx upgrade pdm
升级 pdmpipx uninstall pdm
卸载 pdm首先,通过 venv
创建一个独立于应用程序的虚拟环境,并统一保存在一个目录下以方便管理。例如,可以将虚拟环境存放在 ~/venv
目录下。虚拟环境的名称可以与项目名相同,以便于关联。
conda activate py39
cd ~/venv
python -m venv <project_name>
source <project_name>/bin/activate
pip install -U pip setuptools wheel
进入开发工作目录,例如 ~/workspace
。如果是新建项目,使用 pdm new<项目名称>
。如果是已存在的项目,需要用 pdm 管理,即创建 pyproject.toml
文件。首先,进入项目目录,然后执行 pdm init
。
新项目已创建完成,让我们检查创建了哪些文件,并查看其中关键文件的内容。
可以看到,PDM 为我们创建了一个规范的 Python 项目,包含一个关键的配置文件 pyproject.toml
,相当于 Node.js 项目的 package.json
文件。项目结构包括 src
和 tests
目录,布局类似于 Java 的 Maven 项目。PDM 不仅创建了项目文件,还初始化了一个 git 仓库,并配置好了 .gitignore
文件。
项目中还有一个关键文件 .pdm-python
,建议不要加入 Git 管理。该文件内容,如上图所示,指定了当前项目使用的 Python 解释器路径,即我们之前创建的虚拟环境。有了这个文件,之后在项目目录下执行 PDM 命令时,就无需手动激活环境了。
对于已经存在的 Python 项目,如果缺少 pyproject.toml
文件且未使用 pdm 进行管理,可以按照以下步骤操作:首先激活目标虚拟环境,然后进入项目目录,执行 pdm init
命令以根据提示完成文件的创建。之后,即可使用 pdm 进行项目管理。
主要涉及依赖的添加和移除。在安装之前,先配置 pip 包安装的国内镜像源以加快安装速度。
pdm config pypi.url https://mirrors.aliyun.com/pypi/simple/
若想查看 pdm 的全部配置,直接使用命令 pdm config
。与依赖管理相关的命令主要有以下四条:
pdm add<package_name>
添加依赖,支持精确版本 (例如 pdm add Flask==2.0.1
),兼容版本 (例如 pdm add Django~=4.0
,表示 >=4.0.0, <4.1.0
),最小版本 (例如 pdm add numpy>=1.20
)。pdm remove<package_name>
移除依赖。pdm install
根据 pyproject.toml
配置解析依赖并安装,同时将依赖关系写入 pdm.lock
锁文件。pdm sync
根据 pdm.lock
依赖锁文件复原完整的运行环境。查看依赖关系
pdm list --graph
以树状图的形式展示依赖关系,这对于理解包之间的层级关系非常有帮助。pdm show<package_name>
命令可以显示特定包的详细信息,包括其版本、安装路径、依赖项等。添加开发依赖:对于仅在开发或测试阶段需要的依赖,可以使用 -d
或 --dev
标志将其作为开发依赖添加。开发依赖会添加到 pyproject.toml
的 [tool.pdm.dev-dependencies]
部分。
pdm add pytest --dev
如果项目需要编写使用说明文档,可以添加一个名为 docs
的依赖组。请注意,首先需要手动编辑 pyproject.toml
文件,添加一个 docs = []
的占位符,然后再执行以下命令,以避免出现错误。
pdm add sphinx -G docs
最后,展示一下 UltraFlow 项目的依赖树。
PDM 允许你在项目的隔离环境中直接运行 Python 脚本或命令行工具,而无需手动激活虚拟环境。这通过 pdm run
命令实现。
pdm run python main.py
pdm run pytest
使用 Ruff 进行代码格式化和 lint 检查,执行以下命令前需先配置规则。这里参考了 PDM 开源项目的配置。
[tool.ruff]
respect-gitignore = true
target-version = "py39"
line-length = 120
src = ["src"]
[tool.ruff.format]
quote-style = "single"
[tool.ruff.lint]
extend-select = [
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"FA", # flake8-future-annotations
"PGH", # pygrep-hooks
"RUF", # ruff
"W", # pycodestyle
"UP", # pyupgrade
"YTT", # flake8-2020
]
extend-ignore = ["B018", "B019", "RUF018"]
接下来,你可以执行以下两条命令:格式化代码和进行 lint 检查。
pdm run ruff format.
pdm run ruff check . --fix
PDM 允许你在 pyproject.toml
中定义命令别名,这极大地提高了开发效率和项目可维护性。你可以将常用的复杂命令封装成简单的别名,并通过 pdm run<alias_name>
来执行。
[tool.pdm.scripts]
start = "python -m main"
test = "pytest"
format = "ruff format."
lint = "ruff check. --fix"
接下来,可以使用以下简洁的命令执行相应操作:
pdm run start
启动服务。pdm run test
进行单元测试。pdm run format
格式化代码。pdm run lint
执行代码检查。发布之前,你需要先在 https://pypi.org 注册账号,并完成相关的安全验证。完成这些步骤后,再通过 pdm 进行配置。
pdm config repository.pypi.url https://upload.pypi.org/legacy/
pdm config repository.pypi.username __token__
pdm config repository.pypi.password pypi-<your_token>
接着,你可以通过 pdm publish
命令发布 Python 软件包,例如 UltraFlow。
最后,使用 pdm config
命令来展示我电脑上 PDM 的配置。这里仅截图了自定义部分,可以看到,自定义配置部分本质上是保存在 config.toml
文件中的。