12
9

More than 5 years have passed since last update.

Windows+VSCode+Python(on Linux)のリモートデバッグでブレークポイントが効かない問題と原因と対処

Last updated at Posted at 2019-04-04

恐らく、WindowsでVSCodeを使ってリモートのLinux上のPythonプログラムをデバッグするような人はレアなんでしょうが、私が引っかかって具体的な対処も書かれておらずとても辛かったので、起こった問題、原因、対処法をここで共有します。

また、対処は暫定的なものです。

TL;DR

Windows上のVSCodeにおいて、ドライブレターの大文字・小文字の扱いにより本問題が起きている。

対処としては、launch.jsonpathMappingslocalRootドライブレターを小文字で指定すると動作するようになる。
VSCodeには便利な変数${workspaceFolder}があるので指定したくなるが、これだとドライブレターが大文字になり、本問題が起きる。

関連Issue: https://github.com/Microsoft/vscode-python/issues/2976

そもそもWindowsを使わなければ回避できる

問題

遭遇した環境は以下のような感じ。バージョンが古いという事はあまり関係なさそう。

  • VSCode: 1.32.3
  • VSCode Python Extension: 2019.3.6352
  • Python: 3.6.6
  • ptvsd: 4.2.6

リモート環境はLinux上のコンテナ(docker)でPythonアプリをptvsdを仕込んでリモートデバッグの待ち受けを行っている。

この状態でVSCodeでAtattchしてやるとちゃんと動き始めるが、設定したブレークポイントが効かない。

launch.jsonはこんな感じで、別に何も新しいことはしてない。ドキュメント通りやっている。

doc: https://code.visualstudio.com/docs/python/debugging#_remote-debugging

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "port": 5678,
            "host": "192.168.XXX.XXX",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/mnt"
                }
            ],
        }
    ],
}

/mnt配下にworkspaceFolderの内容のファイルがある。

例外を起こしたときに出てくるスタックトレースからコードジャンプすることは出来るので、マッピングのミスではない気はする。

原因

結構頑張って調べた。

まず、マッピングが正しくない(正確にはファイルパスの置き換え後の結果がリモート上に存在しない)場合、Debug Consoleに以下のようなログが出力され、ブレークポイントが機能しない。

pydev debugger: warning: trying to add breakpoint to file that does not exist: /mnt/c:/path/to/program.py (will have no effect)

これはptvsd上はlaunch.jsonpathMappingsの値を素直にそのまま使うのと、python拡張がsetBreakPoints時に送るファイルパスを小文字で送るという2点の関係から起きているらしい。

実際の動きを追うために以下の2点を行う。

  • launch.jsonの設定に"logToFile": true,を与える
  • リモート側の環境変数にDEBUG_PYDEVD_PATHS_TRANSLATION=1を設定する(docker runなら--env DEBUG_PYDEVD_PATHS_TRANSLATION=1で渡す)

これでファイルパスの置き換えに関するログがデバッグコンソール側に出力されるようになり、ptvsdとのやり取り(JSON)のログが出力される。(extensionが配置されているのフォルダにログが出力される。具体的には%USER_PROFILE%\.vscode\extensions\の下など。)

${workspaceFolder}の挙動を見るには、pathMappingsの値を送る時の値を見れば分かる。
以下のようなログがファイルへ出る。(JSONフォーマット済み、一部センシティブな情報を編集済み)

From Client:
Content-Length: 412

{
    "command": "attach",
    "arguments": {
        "preLaunchTask": "Docker run",
        "name": "Python: Remote Attach",
        "type": "python",
        "request": "attach",
        "port": 5678,
        "host": "192.168.XXX.XXX",
        "pathMappings": [
            {
                "localRoot": "C:\\Path\\To\\Project",
                "remoteRoot": "/mnt"
            }
        ],
        "logToFile": true,
        "debugOptions": [
            "RedirectOutput",
            "WindowsClient"
        ],
        "workspaceFolder": "c:\\Path\\To\\Project",
        "__sessionId": "0a28fee6-35a0-47cf-826b-XXXXXXXXX"
    },
    "type": "request",
    "seq": 2
}

arguments.pathMappings.localRootの値が大文字になっている。なので、${workspaceFolder}はドライブレターを大文字で扱っていることがわかる。

一方で、ブレークポイントを設定する際は、以下のようなログがファイルへ出る。

From Client:
Content-Length: 210

{
    "command": "setBreakpoints",
    "arguments": {
        "source": {
            "sourceReference": 0,
            "path": "c:/Path/To/Program.py"
        },
        "lines": [
            65,
            71
        ],
        "breakpoints": [
            {
                "line": 65
            },
            {
                "line": 71
            }
        ],
        "sourceModified": false
    },
    "type": "request",
    "seq": 16
}

arguments.source.pathの値が小文字になっている。

そして、ptvsd側は以下の処理で前方完全一致で置き換えようとする。

(eclipse_prefix, python_prefix) = (localRoot, remoteRoot)で、translatedはブレークポイント設定時のファイルパス。

ここで置き換えが出来ないと、リモート上のファイルパスとブレークポイントのファイルパスが異なるのでブレークポイントが効かなくなる。といった寸法らしい。

なので、ここを一致させればよい。手っ取り早いのはlaunch.jsonarguments.pathMappings.localRootの値を都合よく合わせる方法だと思う。
具体的には、${workspaceFolder}ではなくc:\\Path\\To\\Projectという形でドライブレターを小文字で明示すればよい。

これに関してはissueも上がっているが、あまり議論が進んでいないように見える。
launch.jsonのlocalRootに${workspaceFolder}を使えないのは面倒なので治ってほしい・・・

12
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9