Visual Studio で Linux 上の Python コードをリモートでデバッグする

この記事では、Visual Studio のインストールをどう構成すれば、リモートの Linux コンピューターで Python コードをデバッグするのをサポートできるかについて説明します。 このチュートリアルは、Visual Studio 2019 バージョン 16.6 に基づいています。

Visual Studio は、Windows コンピューター上で Python アプリケーションをローカルおよびリモートで起動し、デバッグすることができます。 Visual Studio は、さまざまなオペレーティング システム、デバイス、または CPython 以外の Python 実装を、debugpy ライブラリを使用してリモートでデバッグすることをサポートもします。

Visual Studio 2019 バージョン 16.4 以前では、ptvsd ライブラリを使用しています。 Visual Studio 2019 バージョン 16.5 以降は、ptvsd 4 に代わって debugpy ライブラリが使用されています。 debugpy を使用する場合、デバッグ対象の Python コードは Visual Studio がアタッチできるデバッグ サーバーをホストします。 このホスティングでは、サーバーをインポートして有効にするためにコードを少し変更する必要があります。 また、リモート コンピューターのネットワークまたはファイアウォールの構成を調整して、TCP 接続を許可する必要がある場合もあります。

前提条件

  • Python ワークロードをサポートする Visual Studio がインストールされていること。 詳細については、「Visual Studio での Python サポートのインストール」をご覧ください。

  • Mac OSX や Linux などのオペレーティング システムで Python を実行しているリモート コンピューター。

  • リモート コンピューターのファイアウォールで開いているポート 5678 (受信)。これはリモート デバッグの既定値です。

Linux コンピューターを設定する

Azure で Linux 仮想マシンを簡単に作成し、Windows からリモート デスクトップを使用してアクセスすることができます。 仮想マシンの Ubuntu は、Python が既定でインストールされているため便利です。 構成が異なる場合は、他の Python のダウンロード場所について「Python インタープリターをインストールする」を参照してください。

ファイアウォールを構成する

リモート デバッグをサポートするには、リモート コンピューターのファイアウォールで受信ポート 5678 を開く必要があります。

Azure 仮想マシンのファイアウォール規則を作成する方法の詳細については、次の記事を参照してください。

デバッグのためにスクリプトを準備する

次の手順に沿って、Linux で Python コードをデバッグするためのスクリプトを準備します。

  1. リモート コンピューターで、次のコードを使用して guessing-game.py という名前の Python ファイルを作成します。

    import random
    
    guesses_made = 0
    name = input('Hello! What is your name?\n')
    number = random.randint(1, 20)
    print('Well, {0}, I am thinking of a number between 1 and 20.'.format(name))
    
    while guesses_made < 6:
        guess = int(input('Take a guess: '))
        guesses_made += 1
        if guess < number:
            print('Your guess is too low.')
        if guess > number:
            print('Your guess is too high.')
        if guess == number:
            break
    if guess == number:
        print('Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made))
    else:
        print('Nope. The number I was thinking of was {0}'.format(number))
    
  2. pip3 install debugpy コマンドを使用して debugpy パッケージを環境にインストールします。

    Note

    トラブルシューティングに必要な場合に備えてインストールされている debugpy のバージョンを記録しておくことをお勧めします。 debugpy 一覧にも、使用可能なバージョンが表示されます。

  3. 他のコードの前に guessing-game.py ファイルの先頭に次のコードを追加して、リモート デバッグを有効にします。 (厳密な要件ではありませんが、listen 関数を呼び出す前に起動されたバックグラウンド スレッドをデバッグすることはできません。)

    import debugpy
    debugpy.listen(('0.0.0.0', 5678))
    
  4. ファイルを保存し、プログラムを実行します。

    python3 guessing-game.py
    

    listen 関数の呼び出しはバックグラウンドで実行され、ユーザーがプログラムを操作している間、受信接続を待ちます。 必要に応じて、listen 関数を呼び出した後に wait_for_client 関数を呼び出すと、デバッガーがアタッチされるまでプログラムをブロックできます。

ヒント

listen 関数と wait_for_client 関数に加えて、debugpy にはヘルパー関数 breakpoint も用意されています。 デバッガーがアタッチされている場合、この関数はプログラムのブレークポイントとして機能します。 デバッガーがアタッチされている場合は、別の関数 is_client_connected1True を返します。 他の debugpy 関数を呼び出す前に、この結果をチェックする必要はありません。

Python Tools からリモートでアタッチする

次に、ブレークポイントを設定してリモート プロセスを停止する方法の手順を説明します。

  1. ローカル コンピューターでリモート ファイルのコピーを作成し、Visual Studio で開きます。 ファイルの場所は任意ですが、名前はリモート コンピューターのスクリプト名と一致している必要があります。

  2. (省略可能) ローカル コンピューター上の debugpy 用に IntelliSense を使用するには、debugpy パッケージを Python 環境にインストールします。

  3. [デバッグ]>[プロセスにアタッチ] の順に選択します。

  4. [プロセスにアタッチ] ダイアログで、[接続の種類][Python リモート (debugpy)] に設定します。

  5. [接続先] フィールドにコマンド tcp://<ip_address>:5678 を入力します。

    • tcp:// は、接続の種類を伝送制御プロトコル (TCP) として指定します。
    • <ip_address> はリモート コンピューターの IP アドレスです。明示的なアドレスや、myvm.cloudapp.net のような名前を指定できます。
    • :5678 はリモート デバッグ ポート番号です。
  6. Enter キーを選択すると、そのコンピューターで使用できる debugpy プロセスの一覧が生成されます。

    Screenshot that shows how to enter the connection target to see a list of available debugpy processes.

    この一覧の生成後にリモート コンピューターで別のプログラムを起動する場合は、[更新] ボタンを選択します。

  7. プロセスを選択してデバッグし、[アタッチ] を選択するか、プロセスをダブルクリックします。

  8. Visual Studio はデバッグ モードに切り替わり、スクリプトは引き続きリモート コンピューターで実行され、通常のデバッグ機能もすべて使用できます。

    if guess < number: 行のブレークポイントを設定してから、リモート コンピューターに切り替え、別の推測を入力します。 ローカル コンピューター上の Visual Studio はそのブレークポイントで停止し、ローカル変数などが表示されます。

    Screenshot that shows how Visual Studio pauses debugging when a breakpoint is hit.

  9. デバッグを停止すると、Visual Studio はプログラムからデタッチします。 プログラムはリモート コンピューターで引き続き実行されます。 また、debugpy もデバッガーのアタッチを引き続きリッスンするので、いつでもプロセスに再アタッチできます。

接続REST コネクタのトラブルシューティングを行う

接続に関する問題のトラブルシューティングに役立つ次の点を確認します。

  • [接続の種類][Python リモート (debugpy)] を選択していることを確認します。

  • [接続先] のシークレットがリモート コードのシークレットと完全に一致していることを確認します。

  • [接続先] の IP アドレスがリモート コンピューターと一致していることを確認します。

  • リモート コンピューターのリモート デバッグ ポートが開いており、接続先にポート サフィックス (:5678 など) が含まれていることを確認します。

    別のポートを使用するには、debugpy.listen((host, port)) のように、listen 関数の呼び出しでポート番号を指定します。 この場合は、ファイアウォールでもそのポートを必ず開きます。

  • リモート コンピューターにインストールされている debugpy バージョン (pip3 list コマンドによって返されるバージョン) が、Visual Studio Python Tools (PTVS) のバージョンと一致していることを確認します。

    次の表に、有効なバージョン ペアを示します。 必要に応じて、リモート コンピューターの debugpy のバージョンを更新します。

    Visual Studio Python ツール debugpy
    2019 16.6 1.0.0b5 1.0.0b5
    2019 16.5 1.0.0b1 1.0.0b1

Note

Visual Studio 2019 バージョン 16.0 から 16.4 には debugpy ではなく ptvsd が使用されています。 これらのバージョンに関するこのチュートリアルのプロセスは似ていますが、関数名が異なります。 Visual Studio 2019 バージョン 16.5 には debugpy が使用されていますが、関数名は ptvsd のものと同じでした。 listen ではなく、enable_attach を使用します。 wait_for_client ではなく、wait_for_attach を使用します。 breakpoint ではなく、break_into_debugger を使用します。

レガシ デバッグに ptvsd 3.x を使用する

ptvsd 3.x レガシ デバッガーは、Visual Studio 2017 バージョン 15.7 以前の既定値です。

Visual Studio の構成によっては、リモート デバッグに ptvsd 3.x を使用する必要があるかもしれません。

  • Python 2.6、3.1 から 3.4、または IronPython を使用する Visual Studio 2017 バージョン 15.7 以前
  • Python 2.6、3.1 から 3.4、または IronPython を使用する Visual Studio 2019 バージョン 16.5 以降
  • 初期の 4.x バージョン

構成によって前のバージョンのシナリオが実装されている場合、Visual Studio は、"デバッガーはこの Python 環境をサポートしていません" というエラーを表示します。

リモートデバッグをセットアップする

ptvsd 3.x を使用してリモート デバッグを準備するには、次の手順を実行します。

  1. 実行中のスクリプトへのアクセスを制限するために使用するシークレットを設定します。

    Ptvsd 3.x の場合、この enable_attach 関数は、最初の引数として "secret" を渡す必要があります。

    • リモート デバッガーをアタッチするときに、enable_attach(secret="<secret>") コマンドを使用してシークレットを入力します。

    enable_attach(secret=None) コマンドを使用して誰でも接続できるようにすることはできますが、このオプションはお勧めしません。

  2. フォーム tcp://<secret>@<ip_address>:5678 で接続先 URL を作成します。

    • tcp:// は、接続の種類を TCP として指定します。
    • <secret> は、Python コードで enable_attach 関数と共に渡される文字列です。
    • <ip_address> はリモート コンピューターの IP アドレスです。明示的なアドレスや、myvm.cloudapp.net のような名前を指定できます。
    • :5678 はリモート デバッグ ポート番号です。

TCPS プロトコルを使用して接続を保護する

ptvsd 3.x のリモート デバッグ サーバーへの接続は、既定で、シークレットのみで保護されており、データはすべてプレーンテキストで渡されます。 より安全な接続を実現するために、ptvsd 3.x では、セキュリティで保護された形式の TCP プロトコル (TCPS) を使用して SSL がサポートされています。

次の手順に沿って、TCPS プロトコルを使用するよう ptvsd 3.x を構成します。

  1. リモート コンピューターで、openssl コマンドを使用して、キーと自己署名証明書の個別のファイルを生成します。

    openssl req -new -x509 -days 365 -nodes -out cert.cer -keyout cert.key
    
    • openssl プロンプトで、共通名の接続に使用するホスト名または IP アドレスを入力します。

    詳細については、Python ssl モジュール ドキュメントの自己署名証明書を参照してください。 Python のドキュメントで説明されているコマンドは、結合ファイルを 1 つのみ生成することにご注意ください。

  2. enable_attach 関数の呼び出しを変更して certfile 引数と keyfile 引数をコードに含めるには、ファイル名を値として使用します。 これらの引数は、Phyton の標準の ssl.wrap_socket 関数と同じ意味を持ちます。

    ptvsd.enable_attach(secret='my_secret', certfile='cert.cer', keyfile='cert.key')
    

    ローカル コンピューターでのコード ファイルに同じ変更を加えることができます。 このコードは実際には実行されないため、厳密には必要ありません。

  3. リモート コンピューターで Python プログラムを再起動すると、デバッグできる状態になります。

  4. Visual Studio がインストールされた Windows コンピューターの信頼されたルート CA にその証明書を追加して、チャネルをセキュリティで保護します。

    1. リモート コンピューターの証明書ファイルをローカル コンピューターにコピーします。

    2. [コントロール パネル] を開き、[Windows ツール]>[コンピューター証明書の管理] の順に移動します。

    3. certlm [証明書 - ローカル コンピューター] ダイアログで、[信頼されたルート証明機関] ノードを展開し、[証明書] を右クリックして、[すべてのタスク]>[インポート] を選択します。

    4. リモート コンピューターからコピーした .cer ファイルを参照して選択します。

    5. ダイアログ プロンプトを続行して、インポート プロセスを完了します。

  5. Python ツールからリモートでアタッチする」で説明したとおりに、Visual Studio でアタッチ プロセスを繰り返します。

    この例では、tcps://接続先 (または修飾子) のプロトコルとして定義します。

    Screenshot that shows how to specify TCPS as the remote debugging transport with SSL.

接続の問題に対処する

接続の試行中に、Visual Studio で問題が発生する場合があります。 次のシナリオを確認し、必要に応じて適切なアクションを実行します。

  • Visual Studio では、SSL 接続時に、証明書の問題が発生する可能性があることが警告されます。

    アクション: メッセージを無視して続行できます。

    注意

    チャネルは盗聴されないように暗号化されていますが、中間者攻撃にさらされる可能性があることにご注意ください。

  • Visual Studio で、"リモート証明書は信頼されていません" という警告が表示されます。

    問題: 証明書が信頼されたルート CA に正しく追加されていません。

    アクション: Windows コンピューターの信頼されたルート CA に証明書を追加するための手順を再チェックして、もう一度接続を試してください。

    Screenshot of the warning that says the remote SSL certificate isn't trusted.

  • Visual Studio で、"リモート証明書名がホスト名と一致しません" という警告が表示されます。

    問題: 証明書の共通名に適切なホスト名または IP アドレスが指定されていません。

    アクション: 「TCPS を使用して接続を保護する」の手順を再チェックします。 証明書を作成するときは、必ず正しい共通名を使用してください。もう一度接続を試してください。

    Screenshot of the warning that says the remote SSL certificate doesn't match the hostname.