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 仮想マシンのファイアウォール規則を作成する方法の詳細については、次の記事を参照してください。
- Azure portal を使用してネットワーク セキュリティ グループでネットワーク トラフィックをフィルター処理する
- Azure Portal を使用してルート テーブルでネットワーク トラフィックをルーティングする
- Azure portal を使用して Azure Firewall をデプロイして構成する
デバッグのためにスクリプトを準備する
次の手順に沿って、Linux で Python コードをデバッグするためのスクリプトを準備します。
リモート コンピューターで、次のコードを使用して 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))
pip3 install debugpy
コマンドを使用してdebugpy
パッケージを環境にインストールします。Note
トラブルシューティングに必要な場合に備えてインストールされている debugpy のバージョンを記録しておくことをお勧めします。 debugpy 一覧にも、使用可能なバージョンが表示されます。
他のコードの前に guessing-game.py ファイルの先頭に次のコードを追加して、リモート デバッグを有効にします。 (厳密な要件ではありませんが、
listen
関数を呼び出す前に起動されたバックグラウンド スレッドをデバッグすることはできません。)import debugpy debugpy.listen(('0.0.0.0', 5678))
ファイルを保存し、プログラムを実行します。
python3 guessing-game.py
listen
関数の呼び出しはバックグラウンドで実行され、ユーザーがプログラムを操作している間、受信接続を待ちます。 必要に応じて、listen
関数を呼び出した後にwait_for_client
関数を呼び出すと、デバッガーがアタッチされるまでプログラムをブロックできます。
ヒント
listen
関数と wait_for_client
関数に加えて、debugpy にはヘルパー関数 breakpoint
も用意されています。 デバッガーがアタッチされている場合、この関数はプログラムのブレークポイントとして機能します。 デバッガーがアタッチされている場合は、別の関数 is_client_connected1
が True
を返します。 他の debugpy
関数を呼び出す前に、この結果をチェックする必要はありません。
Python Tools からリモートでアタッチする
次に、ブレークポイントを設定してリモート プロセスを停止する方法の手順を説明します。
ローカル コンピューターでリモート ファイルのコピーを作成し、Visual Studio で開きます。 ファイルの場所は任意ですが、名前はリモート コンピューターのスクリプト名と一致している必要があります。
(省略可能) ローカル コンピューター上の debugpy 用に IntelliSense を使用するには、debugpy パッケージを Python 環境にインストールします。
[デバッグ]>[プロセスにアタッチ] の順に選択します。
[プロセスにアタッチ] ダイアログで、[接続の種類] を [Python リモート (debugpy)] に設定します。
[接続先] フィールドにコマンド
tcp://<ip_address>:5678
を入力します。tcp://
は、接続の種類を伝送制御プロトコル (TCP) として指定します。<ip_address>
はリモート コンピューターの IP アドレスです。明示的なアドレスや、myvm.cloudapp.net のような名前を指定できます。:5678
はリモート デバッグ ポート番号です。
Enter キーを選択すると、そのコンピューターで使用できる debugpy プロセスの一覧が生成されます。
この一覧の生成後にリモート コンピューターで別のプログラムを起動する場合は、[更新] ボタンを選択します。
プロセスを選択してデバッグし、[アタッチ] を選択するか、プロセスをダブルクリックします。
Visual Studio はデバッグ モードに切り替わり、スクリプトは引き続きリモート コンピューターで実行され、通常のデバッグ機能もすべて使用できます。
if guess < number:
行のブレークポイントを設定してから、リモート コンピューターに切り替え、別の推測を入力します。 ローカル コンピューター上の Visual Studio はそのブレークポイントで停止し、ローカル変数などが表示されます。デバッグを停止すると、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 を使用してリモート デバッグを準備するには、次の手順を実行します。
実行中のスクリプトへのアクセスを制限するために使用するシークレットを設定します。
Ptvsd 3.x の場合、この
enable_attach
関数は、最初の引数として "secret" を渡す必要があります。- リモート デバッガーをアタッチするときに、
enable_attach(secret="<secret>")
コマンドを使用してシークレットを入力します。
enable_attach(secret=None)
コマンドを使用して誰でも接続できるようにすることはできますが、このオプションはお勧めしません。- リモート デバッガーをアタッチするときに、
フォーム
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 を構成します。
リモート コンピューターで、
openssl
コマンドを使用して、キーと自己署名証明書の個別のファイルを生成します。openssl req -new -x509 -days 365 -nodes -out cert.cer -keyout cert.key
openssl
プロンプトで、共通名の接続に使用するホスト名または IP アドレスを入力します。
詳細については、Python
ssl
モジュール ドキュメントの自己署名証明書を参照してください。 Python のドキュメントで説明されているコマンドは、結合ファイルを 1 つのみ生成することにご注意ください。enable_attach
関数の呼び出しを変更してcertfile
引数とkeyfile
引数をコードに含めるには、ファイル名を値として使用します。 これらの引数は、Phyton の標準のssl.wrap_socket
関数と同じ意味を持ちます。ptvsd.enable_attach(secret='my_secret', certfile='cert.cer', keyfile='cert.key')
ローカル コンピューターでのコード ファイルに同じ変更を加えることができます。 このコードは実際には実行されないため、厳密には必要ありません。
リモート コンピューターで Python プログラムを再起動すると、デバッグできる状態になります。
Visual Studio がインストールされた Windows コンピューターの信頼されたルート CA にその証明書を追加して、チャネルをセキュリティで保護します。
リモート コンピューターの証明書ファイルをローカル コンピューターにコピーします。
[コントロール パネル] を開き、[Windows ツール]>[コンピューター証明書の管理] の順に移動します。
certlm [証明書 - ローカル コンピューター] ダイアログで、[信頼されたルート証明機関] ノードを展開し、[証明書] を右クリックして、[すべてのタスク]>[インポート] を選択します。
リモート コンピューターからコピーした .cer ファイルを参照して選択します。
ダイアログ プロンプトを続行して、インポート プロセスを完了します。
「Python ツールからリモートでアタッチする」で説明したとおりに、Visual Studio でアタッチ プロセスを繰り返します。
この例では、
tcps://
を接続先 (または修飾子) のプロトコルとして定義します。
接続の問題に対処する
接続の試行中に、Visual Studio で問題が発生する場合があります。 次のシナリオを確認し、必要に応じて適切なアクションを実行します。
Visual Studio では、SSL 接続時に、証明書の問題が発生する可能性があることが警告されます。
アクション: メッセージを無視して続行できます。
注意
チャネルは盗聴されないように暗号化されていますが、中間者攻撃にさらされる可能性があることにご注意ください。
Visual Studio で、"リモート証明書は信頼されていません" という警告が表示されます。
問題: 証明書が信頼されたルート CA に正しく追加されていません。
アクション: Windows コンピューターの信頼されたルート CA に証明書を追加するための手順を再チェックして、もう一度接続を試してください。
Visual Studio で、"リモート証明書名がホスト名と一致しません" という警告が表示されます。
問題: 証明書の共通名に適切なホスト名または IP アドレスが指定されていません。
アクション: 「TCPS を使用して接続を保護する」の手順を再チェックします。 証明書を作成するときは、必ず正しい共通名を使用してください。もう一度接続を試してください。