The English Version
PDM 在最近发布了 2.0.0 版本,新特性已基本完成。本文将介绍这次更新的内容。详细改动日志在这里可以看到。
虚拟环境成为项目的默认配置
PDM 在建立之初,是标榜自己是一个支持 PEP 582 包结构的包管理器。但无奈,经过两年的观望,PEP 582 仍旧停留在 Draft 状态,并且迟迟没有进展。 它虽然在一开始令人眼前一亮并吸引了大批初始用户,但这也成为PDM 被主流接纳的一个阻碍,限制了它的推广。同时,虚拟环境在各种 IDE 和工具中有更好的支持。 现在我希望 PDM 并不仅是一个个人兴趣的项目,并且是一个支持 Python 打包最新规范的正经的包管理器,所以在 2.0 中,我们将虚拟环境成为项目的默认配置。
- 在
pdm init
中,如果你没有选择一个已有虚拟环境中的解释器,PDM 会询问是否需要创建一个新的虚拟环境。如果创建,则会把这个虚拟环境作为项目环境, 否则,还是会启用 PEP 582 包结构。 - 当你克隆一个已有的项目,在项目中第一次执行
pdm install
时,PDM 会检查项目中是否存在一个__pypackages__
文件夹1,如果存在,会使用 PEP 582 包结构, 否则会自动为你创建一个虚拟环境并在其中安装依赖。
我们尽可能保证旧的项目不会变化,而只是新项目的默认方式变了。在文档中,PEP 582 也从首页最显眼的位置移动到了子页面中。所以 PDM 依然支持 PEP 582,只是不是默认的方式。
PDM 搭配其他后端
PDM 虽然有一个自己的后端2 pdm-pep517
但它其实没有和任何后端绑定,你依然可以使用比如 flit-core
, hatchling
, setuptools
作为后端,只要它支持读取 PEP 621 的元数据。甚至,你可以混用其他的包管理工具,例如,你完全可以用 flit
来打包你的项目,而只把 PDM 作为依赖管理的工具来使用,因为前者不具备依赖管理的功能。
这就是拥抱标准所带来的巨大好处——工具只要遵循同一个规范,它们之间就可以共同存在,各自完成自己的工作。
不再允许在项目依赖中包含 Editable 的包
原先,在 pyproject.toml
中的 [project]:dependencies
中你可以包含类似 -e ./mypackage
, -e git https://github.com/psf/requests.git@main
这样的 以 Editable 方式安装的包。但这是不符合 PEP 631 规范的,所以在 2.0 中,我们不再支持这种依赖,已有的 editable 包会弹出警告。
但别担心,你还是可以在 [tool.pdm.dev-dependencies]
中包含 Editable 的包,因为实际上它们只在开发中有用。
PDM 全局配置路径遵循 XDG 目录规范
原先 PDM 的全局配置是存在 ~/.pdm
下面的,但在 2.0 中,它们将被放置在 $CONFIG_HOME
下面。具体的值为:
- Linux:
$XDG_CONFIG_HOME/pdm
(一般为~/.config/pdm
) - MacOS:
~/Library/Preferences/pdm
- Windows:
%USERPROFILE%AppDataLocalpdm
你需要做一次性迁移(Linux 为例):
代码语言:javascript复制$ mv ~/.pdm ~/.config/pdm
感谢 @noirbizarre 的贡献。
增加 pdm publish
命令
是的,这个功能是很多用户都希望拥有的,我们终于在 PDM 2.0 中加上了!直接执行 pdm publish
,PDM 会自动打包项目,然后上传到 PyPI。当然,在这之前, 你需要配置好上传所需要的用户密钥。
$ pdm config repository.pypi.username <username>
$ pdm config repository.pypi.password <password>
UI 的 rich 化
PDM 2.0 把 UI 的渲染从原来的 click
halo
改成了 rich
,后者提供了一站式的体验和灵活的配置,构建出了强大而美观的 UI。大部分 UI 都保持了原样,但 rich 的实现更加简单,也更少的 bug。
感谢 @daylinmorgan 的贡献。
不再依赖 pip 内部的 API
PDM 1.x 中寻找包和下载包的部分用到了部分 pip
的 API,但 pip
从来不是作为一个库使用的,而且它遵循的是 CalVer 版本发布,所以即使在小版本的升级中 也会破坏 API 的兼容性,导致 PDM 坏掉。从前 PDM 只能在依赖中限定 pip 的版本范围,但问题是 pip 作为一个基础工具,在不同的 Linux 发行版中可能有各种 patch 导致不能兼容。 所以我们彻底摒弃了使用 pip
的内部 API,转而自己造了一个轮子 unearth
来使用。这将增加稳定性,也方便了下游的打包者。
全面强化的用户脚本系统
在 PDM 之前的版本中我们已经加入了用户脚本系统([tool.pdm.scripts]
,类似 package.json
中的 scripts
),在 2.0 版本中,我们继续增加了许多功能, 让这个系统变得更加强大和灵活。
感谢 @noirbizarre 的贡献。
composite 复合脚本
你可以使用复合脚本来组合多个脚本,它们之间将顺序执行,其中有任一脚本失败,整个复合脚本就失败。
代码语言:javascript复制[tool.pdm.scripts]
lint = "flake8"
test = "pytest"
all = {composite = ["lint", "test"]}
运行 pdm run all
就会执行 lint
和 test
。
用户脚本作为根命令执行
如果你有一个脚本 start
,那么 pdm start
和 pdm run start
同样会执行这个脚本,只要脚本名称没有和其他的命令冲突。
增加更多的钩子
钩子(hook)是在 PDM 执行特定事件前后会触发的回调动作,这可以让插件的开发更加容易。在 PDM 2.0 中我们新增以下钩子:
pre_publish/post_publish
:在上传发布包之前和之后触发pre_run/post_run
:在运行pdm run
之前和之后触发pre_script/post_script
:在运行单个脚本之前和之后触发post_use
:在使用pdm use
切换 Python 解释器之后触发
具体使用方法请查阅文档。
感谢 @noirbizarre 的贡献。
增加 --skip
选项跳过某些钩子或脚本
有了如此多的钩子,很多时候你并不希望它们全都触发,可以使用 --skip
选项来跳过某些钩子或脚本。
# 跳过 pre_install
pdm install --skip pre_install
# 跳过 pre_publish 和 post_publish
pdm publish --skip pre_publish,post_publish
# 跳过所有 post_* 以及 pre_start 钩子和脚本
pdm run --skip:post --skip pre_start start
感谢 @noirbizarre 的贡献。
致谢
在 PDM 2.0 开发中收到了很多帮助、反馈和贡献,特别是 @noirbizarre(他是 flask-restplus
的作者)贡献了大部分用户脚本的功能。 在这里我想贴上他在一个讨论中对 PDM 的评价,引用就不翻译了:
I think the PEP-582 support even if opt-in is already an argument. Given I started using PDM recently after a painful year (maybe 2) looking for a decent solution (Python project management and packaging have been hell recently):
- it just work, no tricks need, no special version (seems logical but just try any other and you will understand)
- scripts support (game changer to me, Poetry only have it through
poet
andPipenv
ones are limited (no env, no shell chaining, no composition...) - supports PEP-621: Poetry and Pipenv don't,
setuptools
has a just recently experimental support - lock file support pnpm-like cache
- editables support (only project so far having both PEP-621 and editables support)
- single tool batteries included (
setuptools
andflit
don't cover the full workflow,poetry
is going under heavy refactoring leading to 2 non-stable codebases, and Pipenv does not support packaging and extensions are very limited, mostly IDE integration) - powerful extensions support dynamic ecosystem: (I can attest it, I contributed a lot lately, everything has been reviewed and accepted, very quickly and the tone was good/kind). I can add transparent and realistic roadmap
- great doc !
- extensive test suite
- have I said it just work