PDM 使用精要

2021年11月01日

PDM 是一个新的 Python 包管理工具 ,它的作者是 PyPa 成员 、Pipenv 目前主要的维护者之一 。在我许久的使用过程里 ,深觉这个工具比目前出现的任何其他 Python 包管理工具都好用 。但是不能说它是 Python 界的 NPM ,因为有些功能 NPM 都没有 ,唯一可惜的是没有被 Guido 钦定 ,不然可以说 NPM 是 node.js 的 PDM 了 。

安装方式一如既往 ,只需要 pipx install pdm 就行 。

PEP-582

PEP-582 是比较新的一个 PEP 规范 ,它约束了 Python 本地包存放的位置——__pypackages__ 。如果使用过 node.js 的人可能会更加明白一点 ,因为 __pypackages__ 就像是 Python 版本的 node_modules

而 PDM 默认情况下就是使用这一标准来存储 、导入本地包 。你只需要使用 pdm --pep582 就可以在 Windows 上直接让 Python 能直接从 __pypackages__ 寻找需要导入的包;在其他系统上则需要把 pdm --pep582 输出的结果追加到自己的 bashrc 里 ,我相信 Linux 用户都是能力出众的极客 ,所以不展开 bashrc 这种小事 。

不过你需要注意 ,pdm --pep582 只能让 Python 执行时能够顺利的 import 到需要的包 ,但却不能让操作系统知道你需要用安装到 __pypackages__ 的可执行文件 ,故而哪怕你激活了 pdm --pep582 ,在运行一些命令时你仍然需要把 pdm run 加在命令之前来执行——就像 npm run 一样 。

由于此规范太过于新 ,所以各编辑器并没有自带支持 ,你需要按照 pdm 文档 里的方式去配置 。

此外 ,这并不是本文的重点 ,如果你有兴趣了解更深 ,可以看 PDM 作者本人的相关博客——PEP 582 的开发日志 (续)

pdm init

按照传统 ,还是初始化配置 ,跟着交互式命令输入即可 。

如果你是从 poetry 迁移过来的 ,那么在最后一步 PDM 会问你是不是要从 Python-Poetry 导入信息 ,可以一键格式转化 。这个功能虽然还是有一点瑕疵 ,有几个字段转换不太正常 (不知道现在修了没) 不过无伤大雅 ,重要信息都无损的转换到 pdm 所需的格式了 。

pdm add && remove

基本用法与其他管理工具相同 ,pdm add index.py 这种格式就可以安装一个 Python 包了 ,移除同理 。

但 pdm 别出心裁地增加了一个非常好用的功能——分组 。以 [baize](https://github.com/abersheeran/baize) 为例 ,包必须的依赖自然不必多说 ,开发时的依赖则非常多 ,而诸如编译所需的包 、构建文档所需的包在正常开发里其实又用不到 。

如果你用的是 poetry 那就没办法了 ,你只能 poetry add package_name --dev 统一划分到开发以来里 。而 PDM 允许你使用 pdm add -dG docs package_name 这样的选项在开发依赖里分组 ,比如 -G docs 是指分到 docs 组 ,也就是构建文档所需地依赖 。

poetry add --dev 这样加进去的开发依赖 ,可以用 package_name[dev] 来安装 ,真正的安装时可选依赖你却只能手动修改 pyproject.toml 来划分 。而 PDM 做到了真正的开发依赖隔离 ,构建出来的包是不会携带任何通过 pdm add -d 命令加进去的依赖的 。而你如果需要指定一些安装时可选的依赖包 ,只需要用 pdm add -G group_name 命令去添加依赖 。

从使用体验来讲 ,分组功能是我选择 PDM 最重要的原因之一 。

pdm install && update

基本用法也和其他管理工具相同 。这两个命令也都支持 -G 命令用以安装 、更新指定分组内指定的依赖 。

pdm run

如果你没有开启 pdm --pep582 却又想让你的 Python 代码能正确地找到你安装的包 ,或是想要执行一个第三方包携带的可执行文件 ,那么你就得把 pdm run 加在你每一个在项目里执行的命令的前面 。

除此之外 ,PDM 还允许你自己包装一些命令 ,就像 npm run 一样 。

  1. # pyproject.toml
  2. [tool.pdm.scripts]
  3. _.env_file = ".env" # 注意这一行配置的意思是解析 `.env` 文件的内容加进各命令执行时的环境变量
  4. serve = "index-cli uvicorn main:app"
  5. migrate = "python -m shoucang migrate main"

pdm export

Python-Poetry 最让人诟病的一点就是一开始没有 export 命令 ,后面妥协了却又只有 requirements.txt 格式的 ,搞得我自己写了一个 poetry2setup 来用 。

PDM 则自带种种格式导出 ,随时可以一键跑路😀 。

配置 PyPi 地址

对于中国用户来说 ,这个功能可以说是必不可缺的 。PDM 作为一个中国人开发的工具自然也包含这个功能 ,而且使用起来相较于 Pipenv 和 Python-Poetry 更加方便 。

  1. pdm config pypi.url https://pypi.tuna.tsinghua.edu.cn/simple

配置 IDE 以支持 PEP 582

现在大多数 IDE 中没有对 PEP 582 的内置支持或插件,您必须手动配置工具.
PDM 将项目范围的配置写入并存储在 .pdm.toml 并且建议您添加以下行 在里面 .gitignore:

  1. .pdm.toml
  2. __pypackages__/

PyCharm

标记 pypackages//lib 作为 来源根 source root. 然后,选择为 Python 解释器 具有相同的 Python 安装 版本.

此外,如果您想使用环境中的工具(例如. pytest), 你必须添加 pypackages//bin 目录到 PATH 对应的变量 运行/调试配置.

VSCode

Add the following two entries to the top-level dict in .vscode/settings.json:

  1. {
  2. "python.autoComplete.extraPaths": ["__pypackages__/<major.minor>/lib"],
  3. "python.analysis.extraPaths": ["__pypackages__/<major.minor>/lib"]
  4. }