ここ最近Pythonのローカル開発環境においては、Poetryで仮想環境+パッケージ管理を行い、direnvで環境変数管理を行うスタンスなのですが、VS Code上でDebug実行しようと思ったら少し設定が必要だったのでメモ的に残しておきます。

Poetry

Poetryは仮想環境構築とパッケージ管理をまとめて実行できる便利なツールです。つまり、venvとpipの代替ツールとなります。詳細は以前記事を書いたのでそちらを参照ください。
poetryでパッケージ・仮想環境を管理

direnv

12 factor を意識して、設定は環境変数に格納するというのが一般的になってきていると思いますが、ターミナルであるディレクトリにcdしたさいに、現在のディレクトリもしくは親ディレクトリを探索して、.envrcが存在していた場合そこに記載されている内容を環境変数にロードしてくれる便利なツールです。別のディレクトリに移動した際は、環境変数はアンロードされます。

インストール

macユーザであればhomebrewで入れるのが一番楽だと思います。その他のインストール方法はこちらを参照ください。

brew install direnv

次にシェルにフックします。Bashの場合は.bashrcに以下のように記載します。その他のシェルの方はこちらを参照ください。

eval "$(direnv hook bash)"

これでdirenvがシェルで有効になりました。

設定

任意のディレクトリに.envrcを作成して、設定したい環境変数を記載していきます。

export PROJECT_DIR=/hoge/fuga
export PROJECT_ID=fuga
export PYTHONPATH="${PROJECT_DIR}:${PYTHONPATH}"

ファイルを作成すると、以下のように.envrcがブロックされているというエラーが出ますので、

direnv: error /hoge/fuga/.envrc is blocked. Run `direnv allow` to approve its content

direnv allowコマンドでブロックを解除してあげます。以後.envrcの内容を変更するたびにdirenv allowを行う必要があります。

direnv allow
direnv: loading /hoge/fuga/.envrc
direnv: export +PROJECT_DIR +PROJECT_ID +PYTHONPATH

これにより、この例ではPROJECT_DIR PROJECT_ID PYTHONPATHが環境変数に格納されました。
以後は、シェルでこの/hoge/fugaディレクトリ配下にcdしただけで自動的に.envrcに記載されている内容が環境変数に格納されるようになります。

VS CodeでDebug実行

通常のPython Debug環境準備

まず、VS CodeのExtensionsアイコンからPythonプラグインをインストールします。

次に、VS CodeのDebugアイコンからDebug画面を開き、Add Configration...をクリックし、Python Fileを選択すると、テンプレートのlaunch.jsonが作成されます。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }
    ]
}

この状態で任意のpythonファイルを開いて、Start DebuggingアイコンをクリックするかF5でDebugをスタートすることができます。

ただし、設定によっては以下のエラーが発生することがあります。その場合は個別に対応が必要です。

  • PoetryでインストールしたパッケージがModuleNotFoundErrorになる
  • direnvで設定したはずの環境変数が参照できない

PoetryでインストールしたパッケージがModuleNotFoundErrorになるケースの対処

PoetryでインストールしたパッケージがModuleNotFoundErrorになるのは、Poetryの仮想環境をVS Codeが認識できてないためです。そのため、認識させてあげればOKです。

一つ目の方法は、.vscode/settings.jsonにPoetryの仮想環境のpythonのpathを直接指定する方法です。
pathはpoetry env infoで確認して、

poetry env info

> Virtualenv
> Python:         3.9.0
> Implementation: CPython
> Path:           /Users/xxxxx/Library/Caches/pypoetry/virtualenvs/myproject-xxxxxxx-py3.9
> Valid:          True

.vscode/settings.jsonにpythonpathとしてそのpathを記載します。

{
    "python.pythonPath": "/Users/xxxxx/Library/Caches/pypoetry/virtualenvs/myproject-xxxxxxx-py3.9"
}

二つ目の方法は、プロジェクト内に仮想環境を作ってしまう方法です。

poetry config virtualenvs.in-project true # --localオプションをつけると設定範囲をプロジェクト内に限定
poetry env remove myproject-xxxxxxx-py3.9 # すでに仮想環境を作ってしまっている場合のみ
poetry env use python # 仮想環境を構築

VS CodeのPythonのDebuggerは賢くて、プロジェクト内にvenvの仮想環境がある場合はその仮想環境をactivateしてくれるため、Poetryでインストールしたパッケージもちゃんと認識してされます。

source /Users/xxxxx/workplace/myproject.venv/bin/activate

direnvで設定したはずの環境変数が参照できないケースの対処

VS CodeのDebug実行で起動されるシェルはログインシェルではないため、.bash_profileは読み込まれません。direnvはフックをシェルに登録することで環境変数格納を実行するのですが、このフックの登録を.bash_profileで行っていると、Debug実行時に環境変数が読み込まれないという問題が発生します。

こちらも対処方法を紹介します。

一つ目は、direnvのフックの処理をちゃんと.bashrcに記載するという対応です。基本はこれで対応すべきです。

二つ目は、direnvを経由せずにDebug実行時に直接環境変数を取り込む方法です。
direnvは.envrcに以下のようにdotenvとだけ書いておくと.envファイルの内容を見に行くようになります。

dotenv

.envファイルには、KEY=VALUEの形式で環境変数を記載することができます。

PROJECT_DIR=/hoge/fuga
PROJECT_ID=fuga
PYTHONPATH="${PROJECT_DIR}:${PYTHONPATH}"

そして、上記.envは、launch.jsonに以下のように設定しておくことで、Debug実行時に環境変数として読み込まれます。

{
    "configurations": [
        {
            "envFile": "${workspaceFolder}/.env",
        }
     ]
}

一つ目の対応は当然やるとして、個人的には二つ目の対応もやることにしました。今後Docker上で実行したくなった時とかに、.envの形式であればそのまま使いまわせるためです。

その他Tips

パッケージ内のコードもDebug

デフォルトだと自分プロジェクト内のコードしかDebugすることができないのですが、launch.jsonに以下の設定を行うことで、パッケージ内のコードもDebugすることができるようになります。

{
    "configurations": [
        {
            "justMyCode": false,
        }
     ]
}