Skip to content

Working with PEP 582#

PEP 582 has been rejected

これはリジェクトされたPEPです。ただし、このフィーチャーがPDMの生成理由であるため、PDMはサポートを保持します。代わりにvirtual environmentsを使用することをお勧めします。

PEP 582を使用すると、依存関係はプロジェクトルートの下の__pypackages__ディレクトリにインストールされます。PEP 582 enabled globallyを使用すると、プロジェクトインタプリタを使用してスクリプトを直接実行することもできます。

When the project interpreter is a normal Python, this mode is enabled.

さらに、あなたのマシンで初めて作業するプロジェクトでは、空の__pypackages__ディレクトリが含まれている場合、PEP 582が自動的に有効になり、virtualenvは作成されません。

Enable PEP 582 globally#

PythonインタプリタにPEP 582パッケージを認識させるには、Pythonライブラリの検索パスにpdm/pep582/sitecustomize.pyを追加する必要があります。

to restart the terminal session to take effect.

pdm --pep582を実行するだけで、環境変数が自動的に変更されます。有効にするには、ターミナルセッションを再起動することを忘れないでください。

The command to change the environment variables can be printed by pdm --pep582 [<SHELL>]. If <SHELL> isn't given, PDM will pick one based on some guesses. You can run eval "$(pdm --pep582)" to execute the command.

You may want to write a line in your .bash_profile(or similar profiles) to make it effective when logging in. For example, in bash you can do this:

環境変数を変更するコマンドは、pdm --pep582 [<SHELL>]で出力できます。<SHELL>が指定されていない場合、PDMはいくつかの推測に基づいて1つを選択します。eval "$(pdm--pep582)"を実行してコマンドを実行できます。

ログイン時に有効にするために、.bash_profile(または同様のプロファイル)に行を書くことができます。例えば、bashでは次のようにすることができます。

1
pdm --pep582 >> ~/.bash_profile

もう一度、ターミナル・セッションを再起動して有効にすることを忘れないでください。

How is it done?

Thanks to the site packages loading on Python startup. It is possible to patch the sys.path by executing the sitecustomize.py shipped with PDM. The interpreter can search the directories for the nearest __pypackage__ folder and append it to the sys.path variable.

Python startupのsite packages loadingのおかげです。PDMに付属のsitecustomize.pyを実行することでsys.pathにパッチを当てることができます。インタプリタはディレクトリから最も近い__pypackage__フォルダを検索し、それをsys.path変数に追加することができます。

Configure IDE to support PEP 582#

現在、ほとんどのIDEにはPEP 582のサポートやプラグインが組み込まれていないため、ツールを手動で設定する必要があります。

PyCharm#

__pypackages__/<major.minor>/libSources Rootとしてマークします。次に、同じ<major.minor>バージョンのPythonインストールをPython interpreterとして選択します。

さらに、環境からのツール(例えばpytest)を使用したい場合は、__pypackages__/<major.minor>/binディレクトリを対応するrun/debug設定のPATH変数に追加する必要があります。

VSCode#

次の2つのエントリを.vscode/settings.jsonのトップレベルdictに追加します。:

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

このファイルは、プラグインpdm-vscodeで自動生成できます。

PEP582をグローバルに有効にする、PEP582を有効にしたのと同じユーザとシェルを使用してVSCodeが実行されていることを確認します。

Cannot enable PEP582 globally?

何らかの理由でPEP582をグローバルに有効にできない場合でも、各プロジェクトでそれぞれの"ラウンチ"を設定することができます。起動設定の.vscode/launch.jsonPYTHONPATH環境変数を設定します。例えば、pytestをデバッグするには次のように実行します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "pytest",
            "type": "python",
            "request": "launch",
            "module": "pytest",
            "args": ["tests"],
            "justMyCode": false,
            "env": {"PYTHONPATH": "__pypackages__/<major.minor>/lib"}
        }
    ]
}

パッケージがsrcディレクトリにある場合は、PYTHONPATHにも追加します。

1
"env": {"PYTHONPATH": "src:__pypackages__/<major.minor>/lib"}
Using Pylance/Pyright?

"python.analysis.diagnosticMode":"workspace"を設定していて、結果として大量のエラー/警告が表示される場合は、ワークスペースディレクトリにpyrightconfig.jsonを作成し、次のフィールドに入力する必要があります。

1
2
3
{
    "exclude": ["__pypackages__"]
}

その後、言語サーバまたはVS Codeを再起動すれば、準備は完了です。将来的には(microsoft/pylance-release#1150)、問題は解決されるかもしれません。

Using Jupyter Notebook?

pdmを使用してjupyter notebookをインストールし、vscodeでpython拡張機能とともに使用する場合は、次のようになります。:

  1. pdm add notebookまたはsoを使用してnotebookをインストールします。
  2. 次のような内容の.envファイルをプロジェクトディレクトリ内に追加します。
1
PYTHONPATH=/your-workspace-path/__pypackages__/<major>.<minor>/lib

上記がまだ動作しない場合は、ノートブックの起動時に環境変数が正しくロードされていない可能性があります。2つの回避策があります。

  1. ターミナルでcode.を実行します。パスが正しく設定された現在のディレクトリに新しいVSCodeウィンドウが開きます。新しいウィンドウでJupyter Notebookを使用します。
  2. 新しいウィンドウを開かない場合は、Jupyter Notebookの先頭で次のコマンドを実行して、パスを明示的に設定します。
1
2
import sys
sys.path.append('/your-workspace-path/__pypackages__/<major>.<minor>/lib')

Reference Issue

PDM Task Provider

さらに、VSCode Task Provider extensionをダウンロードできます。

これにより、VSCodeはpdm scriptsを自動的に検出し、VSCode Tasksとしてネイティブに実行できるようになります。

Neovim#

pyrightneovim-lspを使用して、__pypackages__ディレクトリをパスに追加したい場合は、これをプロジェクトのpyproject.tomlに追加できます。

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

Emacs#

いくつかのオプションがありますが、基本的には、LSPクライアントが参照するパスに__pypackages__を追加するように指示する必要があります。以下に、使用可能なオプションをいくつか示します。:

Using pyproject.toml and pyright#

これをプロジェクトのpyproject.tomlに追加します。:

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

eglot + pyright#

pyrighteglot(Emacs 29に含まれています)を使って、以下を設定に追加します。:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(defun get-pdm-packages-path ()
  "For the current PDM project, find the path to the packages."
  (let ((packages-path (string-trim (shell-command-to-string "pdm info --packages"))))
    (concat packages-path "/lib")))

(defun my/eglot-workspace-config (server)
  "For the current PDM project, dynamically generate a python lsp config."
  `(:python\.analysis (:extraPaths ,(vector (get-pdm-packages-path)))))

(setq-default eglot-workspace-configuration #'my/eglot-workspace-config)

pyrightはグローバルにインストールすることも、プロジェクト内に(おそらくdev依存関係として)インストールすることもできます。たとえば、次のように追加できます。

1
pdm add --dev --group devel pyright

LSP-Mode + lsp-python-ms#

以下は、Emacsでlsp-python-msを使用してPDMを動作させる方法を示すサンプルコードスニペットです。@linw1995

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  ;; TODO: Cache result
  (defun linw1995/pdm-get-python-executable (&optional dir)
    (let ((pdm-get-python-cmd "pdm info --python"))
      (string-trim
       (shell-command-to-string
        (if dir
            (concat "cd "
                    dir
                    " && "
                    pdm-get-python-cmd)
          pdm-get-python-cmd)))))

  (defun linw1995/pdm-get-packages-path (&optional dir)
    (let ((pdm-get-packages-cmd "pdm info --packages"))
      (concat (string-trim
               (shell-command-to-string
                (if dir
                    (concat "cd "
                            dir
                            " && "
                            pdm-get-packages-cmd)
                  pdm-get-packages-cmd)))
              "/lib")))

  (use-package lsp-python-ms
    :ensure t
    :init (setq lsp-python-ms-auto-install-server t)
    :hook (python-mode
           . (lambda ()
               (setq lsp-python-ms-python-executable (linw1995/pdm-get-python-executable))
               (setq lsp-python-ms-extra-paths (vector (linw1995/pdm-get-packages-path)))
               (require 'lsp-python-ms)
               (lsp))))  ; or lsp-deferred