ま、そんなところで。

ニッチな技術系メモとか、車輪を再発明してみたりとか.

debugpyを使ったリモートデバッグ

直接起動できないpythonコードのデバッグに便利

インタプリタやデバッガで直接開始できないpythonコードをデバッグするには、 多くの場合リモートデバッグを使いますね.

pythonでは debugpy というモジュールを使います. github.com

組み込みpythonのdebugに使用できるので便利です.

Step1. 対象コードにdebugpyモジュールのコードを埋め込む

デバッグ対象のコードにデバッグサーバを立ち上げて、接続待機するコードを埋め込みます.

    import debugpy

    # port : 受付port
    port = 5678
    debugpy.listen(port)
    # addressとportを指定する場合はtupleでまとめて指定
    # debugpy.listen((address, port))

    # デバッガが接続されるまで待機
    debugpy.wait_for_client()

たったこれだけ.

Step.2 launch設定

Visual Studio Codeのlaunch設定に, pythonのリモートデバッグ設定を追加します.

// リモートデバッグ用
{
    "name": "debugpy remote debug (Attach)",
    "type": "python",
    "request": "attach",
    "connect": {
        "host": "localhost", // debugpy.listen している接続先ホスト
        "port": 5678           // debugpy.listenしているポート
    },
},

Step.3 接続とアタッチ

debugpy実行側のpythonコードを実行すると、wait_for_client のところで接続待機するので、デバッガを起動してアタッチします.

初回起動時などは、サーバ側が立ち上がるまで数秒かかることがあるので注意.
接続エラーが出た場合は、2〜3秒ほど待ってから再度接続を試みると良いでしょう.

Windowsの場合は特殊な準備が必要

Windowsで使用する場合は、サーバ起動前にdebugpyにインタプリタ環境へのパスを設定してやらないと接続に失敗します.

以下にissueがありました.

github.com

こんな感じです.

# Only windows.
# debugpyにインタプリタパスを通知する
python_path = Path(sys.prefix).joinpath('python.exe')
debugpy.configure(python=str(python_path))

debugpy.listen(address_or_port)
debugpy.wait_for_client()

関数にしておくと便利

まとめて関数化しておくと便利です

def debug_wait_for_attach(listen_to):
    if os.name == 'nt':
        # for windows.
        python_path = Path(sys.prefix).joinpath('python.exe')
        debugpy.configure(python=str(python_path))
    debugpy.listen(listen_to)
    debugpy.wait_for_client()

リファレンス