PEP 582

PEP 582 已被拒绝

这是一个已被拒绝的 PEP。然而,由于这个特性是 PDM 诞生的原因,PDM 将继续保留对它的支持。我们建议改用虚拟环境

通过PEP 582,依赖项将被安装到项目根目录下的__pypackages__目录中。当全局启用 PEP 582时,你还可以使用项目解释器直接运行脚本。

如果项目解释器是一个普通的 Python,此模式将被启用。

此外,在首次在机器上使用的项目中,如果它包含一个空的__pypackages__目录,PEP 582 将自动启用,并且不会创建 virtualenv。

全局启用 PEP 582

要使 Python 解释器了解 PEP 582 包,需要将pdm/pep582/sitecustomize.py添加到 Python 库搜索路径中。

Windows

只需执行pdm --pep582,环境变量将自动更改。不要忘记重新启动终端会话以生效。

Mac 和 Linux

pdm --pep582 [<SHELL>]可以打印出更改环境变量的命令。如果未给出<SHELL>,PDM 将基于一些猜测选择一个。 你可以运行eval "$(pdm --pep582)"来执行该命令。

你可能希望在.bash_profile(或类似的配置文件)中写入一行,以便在登录时生效。例如,在 bash 中,你可以这样做:

  1. pdm --pep582 >> ~/.bash_profile

再一次,不要忘记重新启动终端会话以生效。

如何实现?

感谢 Python 启动时的站点包加载。通过执行 PDM 附带的sitecustomize.py,可以修改sys.path。解释器可以搜索目录中最近的___pypackage__文件夹,并将其添加到sys.path变量中。

配置 IDE 以支持 PEP 582

现在大多数 IDE 中没有内置支持或插件用于 PEP 582,你需要手动配置你的工具。

PyCharm

__pypackages__/<major.minor>/lib标记为源代码根目录。 然后,选择一个具有相同<major.minor>版本的 Python 安装作为Python 解释器

此外,如果你想使用环境中的工具(例如pytest),你必须将__pypackages__/<major.minor>/bin目录添加到相应运行/调试配置中的PATH变量。

VSCode

.vscode/settings.json的顶层字典中添加以下两个条目:

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

这个文件可以使用插件pdm-vscode自动生成。

全局启用 PEP582,并确保 VSCode 使用你启用 PEP582 的相同用户和 shell 运行。

Neovim

如果使用nvim-lsppyright,并且希望将你的__pypackages__目录添加到路径中,你可以将它添加到项目的pyproject.toml中。

  1. [tool.pyright]
  2. extraPaths = ["__pypackages__/<major.minor>/lib/"]

Emacs

你有几个选项,但基本上你将想要告诉 LSP 客户端将__pypackages__添加到它查看的路径中。这里有一些可用的选项:

使用 pyproject.toml 和 pyright

将此添加到项目的pyproject.toml中:

  1. [tool.pyright]
  2. extraPaths = ["__pypackages__/<major.minor>/lib/"]

eglot + pyright

使用pyrighteglot(包含在 Emacs 29 中),将以下内容添加到你的配置中:

  1. (defun get-pdm-packages-path ()
  2. "For the current PDM project, find the path to the packages."
  3. (let ((packages-path (string-trim (shell-command-to-string "pdm info --packages"))))
  4. (concat packages-path "/lib")))
  5. (defun my/eglot-workspace-config (server)
  6. "For the current PDM project, dynamically generate a python lsp config."
  7. `(:python.analysis (:extraPaths ,(vector (get-pdm-packages-path)))))
  8. (setq-default eglot-workspace-configuration #'my/eglot-workspace-config)

你将需要全局安装 pyright,或者在项目中安装(可能作为开发依赖)。你可以使用以下命令添加:

  1. pdm add --dev --group devel pyright

LSP-Mode + lsp-python-ms

以下是如何在 Emacs 中使用lsp-python-ms使 PDM 工作的示例代码片段。由@linw1995贡献。

  1. ;; TODO: Cache result
  2. (defun linw1995/pdm-get-python-executable (&optional dir)
  3. (let ((pdm-get-python-cmd "pdm info --python"))
  4. (string-trim
  5. (shell-command-to-string
  6. (if dir
  7. (concat "cd "
  8. dir
  9. " && "
  10. pdm-get-python-cmd)
  11. pdm-get-python-cmd)))))
  12. (defun linw1995/pdm-get-packages-path (&optional dir)
  13. (let ((pdm-get-packages-cmd "pdm info --packages"))
  14. (concat (string-trim
  15. (shell-command-to-string
  16. (if dir
  17. (concat "cd "
  18. dir
  19. " && "
  20. pdm-get-packages-cmd)
  21. pdm-get-packages-cmd)))
  22. "/lib")))
  23. (use-package lsp-python-ms
  24. :ensure t
  25. :init (setq lsp-python-ms-auto-install-server t)
  26. :hook (python-mode
  27. . (lambda ()
  28. (setq lsp-python-ms-python-executable (linw1995/pdm-get-python-executable))
  29. (setq lsp-python-ms-extra-paths (vector (linw1995/pdm-get-packages-path)))
  30. (require 'lsp-python-ms)
  31. (lsp)))) ; or lsp-deferred