みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Djangoで作成したDockerイメージをVS Codeでデバッグする

VS CodeのPython拡張機能を使うことで,Pythonスクリプトを簡単にデバッグすることができます.これをDockerで実行中のDjangoプロジェクトで使用できるようにします.

Python - Visual Studio Marketplace

debugpyとVS Codeの設定

Microsoftが開発しているPython用のデバッガーを使います.

GitHub - microsoft/debugpy: An implementation of the Debug Adapter Protocol for Python

対象となるスクリプトに組み込んで,httpリクエストをlistenするようにしておき,VS CodeのPython拡張機能でデバッグを開始して接続します.

以下のような,ValueErrorを発生させるPythonスクリプトと,localhostのport 9001のdebugpyに接続するlaunch.jsonを用意します.

r.py

import debugpy

debugpy.listen(("localhost", 9001))
print("Waiting for VSCode debugger.")
debugpy.wait_for_client()
a = 1
b = "ab"
raise ValueError()

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote (port 9001)",
            "type": "python",
            "request": "attach",
            "port": 9001,
            "host": "localhost",
        },
    ]
}

これらを実行すると,以下のようにVS Codeでデバッグすることができます.ValueErrorの直前で実行されているb = "ab"により作成された変数bの内容なども確認することができています.

f:id:atsuhiro-me:20210202193927p:plain

Dockerで使用

debugpyはhttpリクエストを利用しているので,かなり自由度が高く,少し設定を工夫すればDockerで実行中のPythonスクリプトもデバッグすることができます.

まず,port 9001にホストからアクセスできるように設定します.

docker-compose.yaml

version: '3'

services:
  sample:
    ports:
      - "9001:9001"

localhostを0.0.0.0に変更します.

import debugpy

debugpy.listen(("0.0.0.0", 9001))
print("Waiting for VSCode debugger.")
debugpy.wait_for_client()

これでデバッグができるようになります.

Djangoのリロードに対応する

manage.pyに以下のようなコードを追加します.

def main():
    if not os.environ.get("RUN_MAIN"):
        import debugpy
        debugpy.listen(("0.0.0.0", 9001))
        print("Waiting for vscode debugger...")
        debugpy.wait_for_client()
        print("connected.")

django/autoreload.py at master · django/django · GitHub

これにより,ソースコードの変更でDjangoがリロードしてもデバッグが継続されるようになります.

pathMappings

Dockerの中とホストのパスが一致しないと,エラーが発生したときにソースコードのファイルが正しく自動で開かれないので,launch.jsonにpathMappingsを設定します.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote (port 9001)",
            "type": "python",
            "request": "attach",
            "port": 9001,
            "host": "0.0.0.0",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}/django",
                    "remoteRoot": "/workdir"
                }
            ],
        },
    ]
}

Debugging configurations for Python apps in Visual Studio Code

まとめ

Djangoのエラー表示は親切なのですが,debugpyを使用した方が分かりやすいので,これらの設定をおすすめします.