PDM是一款国人开发的类似pip、conda的python包管理器,允许将一个python项目所需的包都放在当前目录下,支持创建多种虚拟环境,也允许自定义命令。其开发受到Node.js包管理器 pnpm的影响

PDM可基于同一个python解释器构建多个虚拟环境,因此比conda更轻量,比pip更灵活。本文我们了解pdm的基本用法

初始化

安装pdm推荐使用pipx,这是一个python命令行工具安装器。pdm会被安装在 /home/username/.local/bin目录下

sudo apt install pipx
pipx install pdm
pipx ensurepath

使用 pdm init命令初始化当前python项目,会列出当前能找到的所有python解释器。如果你同时使用了conda,无法检测到其他conda环境下的python。选择python版本后,其他选项保持默认即可

初始化的目录结构形如

├── .gitignore
├── .pdm-python
├── .venv
│   ├── .gitignore
│   ├── bin
│   ├── lib
│   └── pyvenv.cfg
├── README.md
├── __pycache__
├── pyproject.toml
├── src
│   └── tplot
└── tests
    ├── __init__.py
    └── __pycache__

pyproject.toml包含项目的构建元数据、项目的依赖环境,也可在此定义快捷命令,类似JavaScript的 package.json

pdm.lock存储了详细的包版本,类似JavaScript的 package-lock.json, yarn.lock, package-lock.json

.venv存储了虚拟环境,类似JavaScript的 node_modules

.pdm-python 存储当前项目使用的python路径

项目的所有代码写在 src/projname下,测试文件写在 tests

依赖管理

可为项目添加各种依赖项,add命令会在修改 pyproject.toml的同时安装好需要的包

# 添加依赖项
pdm add pandas seaborn
# 加入本地包,注意路径必须以./开头
pdm add ./sub-package
# 添加仅开发时的依赖项
pdm add -dG test pytest
# 删除依赖项
pdm remove requests
# 列出安装的所有包
pdm list
# 列出依赖路径
pdm list pandas --tree
# 根据pyproject.toml安装依赖项
pdm install

以上是从0开始一个新项目的做法。但pdm如何接管老项目?或者如何在 git clone之后,创建合适的运行环境?

其实,只要项目中存在 requirements.txt,调用 git init之后,就可以选择将 requirements.txt的依赖默认添加到 pyproject.toml

如果是 git clone来的项目,再执行 pdm install即可

激活默认环境

以上,pdm默认创建名为 in-project的虚拟环境,这也是当前项目的默认环境。可 pdm venv list列出

(base) william@winLab:~/proj/tplot$ pdm venv list
Virtualenvs created with this project:

*  in-project: /home/william/proj/tplot/.venv

如果你使用VS code,在terminal中cd到项目目录,使用 code .打开项目,即可自动激活 in-project虚拟环境

否则,进入python也检测不到虚拟环境中的包。需要使用shell命令激活虚拟环境

(base) william@winLab:~/proj/xplot$ eval $(pdm venv activate in-project)
(xplot-3.10) (base) william@winLab:~/proj/xplot$ 

快捷命令

pyproject.toml中,可在 [tool.pdm.scripts]部分自定义快捷命令

[tool.pdm.scripts]
start = "flask run -p 54321"

然后,直接执行以下命令,即可启动flask

pdm run start

如果需要指定运行目录、环境变量,可分别指定`start.cmd, start.working_dir, start.env

所有快捷命令共享的全局环境变量,可指定

[tool.pdm.scripts]
_.env_file = ".env"

切换python版本

可以通过pdm安装多个python版本,会保存在 /home/username/.local/share/pdm/python目录。这些python版本对所有项目都可见

pdm python install 3.8
# 列出通过pdm安装的python
pdm python list

然后,基于3.8版本创建另一个虚拟环境,会保存在 /home/username/.local/share/pdm/venvs目录。该虚拟环境仅对当前项目可见

pdm venv create --name test3.8 3.8

此时,如果激活虚拟环境 test3.8,pdm记录的项目信息,仍然是默认的 in-project环境

(xplot-3.10) (base) william@winLab:~/proj/xplot$ eval $(pdm venv activate test3.8)
(xplot-3.8) (base) william@winLab:~/proj/xplot$ pdm info
PDM version:
  2.15.4
Python Interpreter:
  /home/william/proj/xplot/.venv/bin/python (3.10)
Project Root:
  /home/william/proj/xplot

如果需要将项目默认环境转换为 test3.8,使用 pdm use命令,然后重新安装所需依赖。安装依赖时很有可能报错,可能需要 pdm remove依赖,重新 pdm add

pdm use --venv test3.8
pdm instll

但是,对同一个项目切换python版本是很少见的需求,一般情况不推荐这么做。更常见的需求是开发python包时的多版本环境测试,此时更推荐使用Nox

结语

以上我们梳理了pdm为Python使用带来的便利。当你需要开发自己的Python包时,pdm的好处会得到淋漓尽致的体现——是的,你可以完全抛弃poetry等传统的开发工具了

但即使你无心开发Python包,pdm也会使你的Python项目结构更加合理、依赖更加清晰,使项目在机器间迁移和扩展的成本降低

玩的开心!