閉じる

VSCodeでPythonをスマートにデバッグする方法|print卒業の実践ハウツー

VSCodeはPython開発において、ただコードを書くためだけのエディタではありません。

デバッガを使いこなすことで、print文に頼らず、バグの原因を短時間で特定できる強力な開発環境になります。

本記事では、VSCodeのPythonデバッグの基本から応用までを、図解とサンプルコードを交えながら丁寧に解説します。

printデバッグから「卒業」したい方は、ぜひ順番に読み進めてみてください。

VSCodeでPythonデバッグを始める前に

VSCodeでPythonをデバッグするメリット

VSCodeでPythonをデバッグする最大のメリットは、「プログラム実行中の状態を、その場で自由に観察・操作できること」です。

printデバッグでは、実行前にどこにprintを仕込むかを考え、実行後に大量のログをスクロールして原因を探す必要があります。

一方、VSCodeデバッガでは、一時停止した瞬間の変数の中身や関数の呼び出し履歴を、止めたいタイミングで自由に確認できます。

また、VSCodeは以下の点でPythonデバッグに向いています。

  • 専用のPython拡張が用意されており、インストールだけでデバッグ機能まで一体化して使えること
  • Jupyter Notebook、ターミナル、Gitなどと統合されており、デバッグ以外の開発作業との行き来がスムーズなこと
  • Windows、macOS、Linuxに対応し、WSLやコンテナ内のPython環境もデバッグできる柔軟性があること

このように、VSCodeを使えば、単なるエディタではなく統合されたPython開発環境としてデバッグを行うことができます。

printデバッグの限界と非効率さ

Python学習の初期段階では、printを使って値を確認する方法は非常にわかりやすく、手軽です。

しかし、規模が少し大きくなると、printデバッグには次のような限界が現れます。

まず、条件分岐やループが増えると、「どこにprintを書けば良いか」を考えるだけでも負担になります。

さらに、何度も実行と修正を繰り返すうちに、ソースコードがprint文だらけになり、本来のロジックが見えにくくなってしまいます。

また、print文は基本的に「書いた場所での情報」しか出力できません。

関数の呼び出し履歴(コールスタック)や、その時点でのすべての変数の一覧、条件によって特定の状況でだけ止めたいといった高度な制御はできません。

このため、複雑なバグほど、printの個数と試行回数だけが増えていくという非効率な状態に陥りがちです。

VSCodeのデバッガを使えば、printを一切書き換えることなく、任意の行で自由に停止し、そのタイミングで必要な情報だけを観察できます。

さらに、デバッグが終わった後にprintを消し忘れる心配もなくなります。

必要な拡張機能(Python拡張など)のインストール

VSCodeでPythonを本格的にデバッグするには、Microsoft公式のPython拡張機能をインストールする必要があります。

インストール手順は次のようになります。

  1. VSCodeを起動し、左のアクティビティバーから拡張機能アイコンをクリックします。
  2. 検索ボックスにPythonと入力します。
  3. 発行元がMicrosoftPython拡張を選択し、「Install」ボタンを押します。
  4. 併せて、Jupyter拡張やPylance拡張も自動的に提案される場合がありますが、これらもPython開発には便利です。

Python拡張は、次のような役割を担います。

  • Pythonコードの構文ハイライトや補完機能
  • Lint、フォーマッタとの連携
  • 仮想環境の検出
  • デバッガ(debugpy)の統合

拡張機能のインストールが完了すると、VSCodeのステータスバー(左下)に選択中のPythonインタプリタが表示されるようになります。

この表示は、次のセクションで扱うPython環境の設定とも密接に関係します。

Python環境(venv, Anaconda)の基本設定

VSCodeでデバッグを行う際には、どのPython環境で実行するかを明確にしておく必要があります。

代表的な環境は次の2種類です。

  • 標準のvenvによる仮想環境
  • AnacondaやMinicondaによるConda環境

仮想環境を使う理由は、プロジェクトごとに依存ライブラリのバージョンを分離し、他のプロジェクトと干渉しないようにするためです。

VSCodeでは、次のような流れで環境を設定します。

まず、ターミナル(統合ターミナルでも可)でプロジェクトフォルダに移動し、仮想環境を作成します。

Shell
# venvで仮想環境を作成
python -m venv .venv

# Windows: 仮想環境を有効化
.venv\Scripts\activate

# macOS / Linux: 仮想環境を有効化
source .venv/bin/activate

続いて、VSCodeを開き、左下ステータスバーに表示されているPythonインタプリタ名をクリックします。

すると、利用可能なPython環境の一覧が表示されますので、先ほど作成した.venvを選択します。

Conda環境を利用する場合も考え方は同じで、ターミナルでconda createしてから、VSCode上でその環境を選択します。

選択されたインタプリタが、そのままデバッグ時に利用されるPythonになりますので、ここがずれていないかを最初に確認しておくことが重要です。

VSCodeデバッガの基本操作を理解する

デバッグ構成(launch.json)の作成と設定

VSCodeでPythonをデバッグするには、デバッグ構成(launch.json)を用意します。

これは「どのファイルを、どのようなオプションで実行するか」を定義する設定ファイルです。

はじめてデバッグを行う場合、次の手順で自動生成できます。

  1. 左のアクティビティバーから「実行とデバッグ」(虫のアイコン)をクリックします。
  2. 中央に表示される実行とデバッグパネルで、「launch.jsonファイルを作成」を選択します。
  3. 環境の選択でPythonを選びます。

すると、次のような.vscode/launch.jsonが作成されます。

JSONC
{
    // デバッグ構成の配列
    "configurations": [
        {
            "name": "Python: Current File", // デバッグ構成の表示名
            "type": "python",               // デバッガの種類
            "request": "launch",            // 実行方法(launch/attach)
            "program": "${file}",           // 実行するPythonファイル
            "console": "integratedTerminal",// 統合ターミナルで実行
            "justMyCode": true              // 自分のコードのみステップ実行
        }
    ]
}

${file}は、現在開いているエディタのファイルを意味します。

複数のエントリポイントがあるプロジェクトでは、programmain.pyなど特定のファイルに固定することもできます。

launch.jsonは、プロジェクトごとに作成し、Gitで共有することで、チーム全員が同じデバッグ方法を簡単に再現できるという利点もあります。

ブレークポイントの設定と条件付きブレークポイント

Pythonデバッグの要は、ブレークポイントです。

ブレークポイントとは、「ここに到達したら一時停止してほしい」という目印のことです。

ブレークポイントを設定するには、エディタ左の行番号付近をクリックします。

赤い丸が表示され、その行にブレークポイントが設定されます。

もう一度クリックすると解除されます。

さらに、VSCodeでは「条件付きブレークポイント」を設定することができます。

これは、単に行に到達しただけで止まるのではなく、特定の条件を満たした時だけ一時停止する高度な機能です。

例として、次のようなPythonコードを考えてみます。

Python
# sample_breakpoint.py

def find_target(numbers, target):
    for i, n in enumerate(numbers):
        # ここにブレークポイントを置いて、ある条件のときだけ止まりたい
        if n == target:
            return i
    return -1

if __name__ == "__main__":
    data = list(range(100))
    index = find_target(data, 42)
    print("Index:", index)

このforループの行にブレークポイントを設定し、その赤丸を右クリックすると「条件の編集」が選べます。

たとえばn == 42と入力すれば、nが42になったときにだけループが停止します。

これにより、「100回あるループのうち、特定の1回だけを詳しく追いたい」といった場面でも、printを仕込むことなく効率的にデバッグが可能になります。

ステップ実行(step over/into/out)の使い分け

ブレークポイントでプログラムが一時停止したら、ステップ実行を使って、1行ずつ処理の流れを追うことができます。

代表的な操作は次の3つです。

  • ステップオーバー(step over)
  • ステップイン(step into)
  • ステップアウト(step out)

それぞれのイメージを簡単に説明します。

ステップオーバーは、「現在の行を実行するが、その行で呼ばれる関数の内部には入らない」動きです。

関数の中身を詳しく見る必要がない場合に使います。

ステップインは、「現在の行が関数呼び出しなら、その中に入って1行目から実行を追う」動きです。

関数内部のロジックにバグがあると疑われる場合に有効です。

ステップアウトは、「今入っている関数の残りを一気に実行し、呼び出し元まで戻って停止する」操作です。

関数の中をざっと確認して、もう中は追わなくてよいと判断したときに使います。

これらを組み合わせることで、必要な部分は細かく、不要な部分はまとめて進めることができ、デバッグのテンポを保ちやすくなります。

変数ウォッチとローカル変数の確認方法

ブレークポイントで停止中は、変数の中身をリアルタイムで確認できます。

VSCodeでは、右側のデバッグペインに「変数」というセクションがあり、ここにローカル変数とグローバル変数が一覧表示されます。

たとえば、次のようなコードをデバッグ中だとします。

Python
# sample_variables.py

def calc_total(prices, tax_rate):
    subtotal = sum(prices)
    tax = int(subtotal * tax_rate)
    total = subtotal + tax
    return total

if __name__ == "__main__":
    prices = [120, 300, 450]
    tax_rate = 0.1
    result = calc_total(prices, tax_rate)
    print("Total:", result)

calc_total関数の中にブレークポイントを置いて実行すると、「変数」ペインにはpricestax_ratesubtotalなどがツリー形式で表示されます。

リストや辞書は展開して中身を見ることができます。

さらに、特定の変数や式だけを継続的に監視したい場合は、「ウォッチ」セクションを使います。

ここにはsubtotallen(prices)といった任意の式を追加でき、ステップを進めるたびに値が更新されます。

これにより、重要な変数だけを集中して追うことができます。

コールスタックとスレッドの見方

コールスタックは、「今の場所に到達するまでに、どの関数からどの関数が呼ばれてきたか」を表す履歴です。

バグの原因を探る際によくあるのは、「この関数がいつ、どこから呼ばれたか」を知りたいという状況です。

VSCodeの「コールスタック」セクションには、現在のスレッドごとに関数の呼び出し階層が表示されます。

スタックの一番上が今実行中のフレーム、その下に呼び出し元、そのまた下にさらに呼び出し元、という順に並びます。

任意のフレームをクリックすると、その時点に対応するソースコードの行が表示され、ローカル変数もその時点の状態に切り替わります

これは、例えば例外が発生した時に、その直前の状態だけでなく、呼び出し元の状態も合わせて確認したい場合に非常に役立ちます。

マルチスレッドプログラムの場合は、スレッドごとに別のスタックが表示されます。

どのスレッドで問題が起きているのかを見極めるのにも、コールスタックとスレッドの一覧は重要な情報源になります。

print卒業のための実践テクニック

ログポイントでprintの代わりにログを出す

VSCodeには、ログポイント(Logpoint)という便利な機能があります。

これは「一時停止はせずに、指定したメッセージだけをログとして出力するブレークポイント」です。

考え方としてはprintに似ていますが、ソースコードを変更せずに設置できる点が大きな違いです。

ログポイントを作るには、行番号の左を右クリックして「ログポイントの挿入」を選びます。

すると、メッセージ入力欄が表示されるので、例えば次のように入力します。

n = {n}, i = {i}

中括弧で囲んだ部分には、その時点の変数の値が埋め込まれます。

実行すると、プログラムは止まらずに進みますが、デバッグコンソールやターミナルに指定したログが出力されます。

ポイントは、ログポイントはデバッグセッション中だけ有効であり、デバッグをやめれば自動的に「無効なprint」と同じ状態になることです。

ソースコードにprintを書き足したり削除したりする必要がないため、コードが散らかりません。

式の評価とデバッグコンソールの活用

デバッグ中にプログラムが停止している間は、デバッグコンソールを使ってPythonの式をインタラクティブに評価できます。

これは、停止中のスコープ内にある変数や関数を自由に扱えるREPLのようなものです。

たとえば、次のようなコードで一時停止しているとします。

Python
# sample_console.py

def process(items):
    total = sum(items)
    avg = total / len(items)
    # ここで一時停止して、itemsやavgをいろいろ試したい
    return avg

if __name__ == "__main__":
    data = [10, 20, 30, 40]
    print(process(data))

このとき、デバッグコンソールに次のような式を入力できます。

len(items)
items[1:]
avg * 2

これにより、変数の値を一時的に変えてみたり、新しい式を試して結果を見るといったことが、ソースコードを書き換えることなく行えます。

問題の切り分けや、アルゴリズムの検証に非常に役立つ機能です。

例外発生時に自動で止める

一般的なブレークポイントは「この行に到達したら止まる」という動作ですが、VSCodeでは例外が発生した瞬間に止めることもできます。

これが「例外ブレークポイント」です。

設定は「実行とデバッグ」ビューの「ブレークポイント」セクションから行います。

「例外ブレークポイントの設定」(あるいは類似のボタン)を開くと、例えば次のような選択肢があります。

  • すべての例外
  • 未処理の例外

「未処理の例外」にチェックすると、try-exceptで捕まえられていない例外が発生したときに、自動的にその行で停止します。

これにより、「どこかで例外が起きてプログラムが落ちてしまうが、どこなのかわからない」といった状況を素早く特定できます。

さらに、特定の例外のみを対象にしたい場合は、Python側の設定やフィルタリングを工夫することで、例えばValueErrorのときだけ止まる、といった運用も可能です。

複雑なデータ構造の中身を効率的に確認する

Pythonでは、リストや辞書、クラスインスタンスなど、複雑なデータ構造がよく登場します。

printでこれらの中身を確認しようとすると、改行やインデントのない長い1行になってしまい、どこに何があるのか非常に見づらくなります。

VSCodeの変数ビューでは、複雑なオブジェクトもツリーとして展開できるため、階層構造を保ったまま中身を確認できます。

特に次のような点が便利です。

  • リストの特定インデックスだけを開いて中身を見ることができる
  • 辞書のキーごとに展開されるため、必要なキーだけを確認しやすい
  • クラスインスタンスでは属性名ごとに値が表示される

また、変数を右クリックして「値をコピー」したり、デバッグコンソールでpprintを使って整形表示したりすることで、ログとして残したい場合にも対応できます。

複雑な構造こそ、視覚的に展開できるデバッガの強みが生きる領域です。

非同期処理とマルチスレッドのデバッグポイント

非同期処理(asyncio)やマルチスレッド処理では、処理の流れが直線的ではなくなるため、printだけで追うのはかなり困難です。

VSCodeのデバッガは、スレッドやタスクごとの実行状態を切り替えて見ることができるため、こういったコードでも効果的にデバッグが行えます。

async関数の中にも通常通りブレークポイントを置くことができます。

awaitで一時停止やタスク切り替えが発生する場合でも、VSCodeは現在どの箇所が実行中なのかを把握し、ステップ実行や変数確認をサポートしてくれます。

マルチスレッドの場合は、「コールスタック」ペインでスレッドごとにスタックが分かれて表示されます。

指定のスレッドを選択することで、そのスレッドの現在位置や変数を確認できます。

デッドロックやレースコンディションの原因調査にも役立つため、並行処理を書く際にはぜひ活用したい機能です。

ユニットテストをVSCodeからデバッグ実行する

Python開発では、ユニットテストをデバッグする機会も多くなります。

VSCodeのPython拡張は、pytestやunittestなどのテストフレームワークと連携し、テスト単位でのデバッグ実行をサポートしています。

テスト機能を利用するには、まずワークスペースでPython拡張の「テスト」機能を有効にします。

コマンドパレットからPython: Configure Testsを選び、pytestなどを指定すると、テストの自動検出が始まります。

テストが認識されると、「テスト」ビューに関数単位で表示されるようになります。

ここで任意のテストの横にある「デバッグ」アイコンをクリックすると、そのテストだけを対象にデバッガが起動します。

テストコードやテスト対象コードにブレークポイントを置いておけば、失敗しているテストの原因をピンポイントに調べることができます。

Python開発を加速するVSCodeデバッグ応用

launch構成のテンプレート化でプロジェクトを共通化

プロジェクトが大きくなると、実行したいシナリオが複数出てきます。

たとえば「通常起動」「特定のサブコマンド」「テスト実行」などです。

このようなときには、launch構成をテンプレート化しておくと便利です。

例として、次のようなlaunch.jsonを考えてみます。

JSONC
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "App: Main",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/main.py",
            "console": "integratedTerminal"
        },
        {
            "name": "Script: Data Import",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/tools/import_data.py",
            "args": ["--dry-run"],
            "console": "integratedTerminal"
        },
        {
            "name": "Tests: Pytest",
            "type": "python",
            "request": "launch",
            "module": "pytest",
            "args": ["-q"],
            "console": "integratedTerminal"
        }
    ]
}

nameをわかりやすく付けておくことで、デバッグビューのドロップダウンからすぐに目的の構成を選べます。

また、このファイルをリポジトリに含めておけば、チーム全員が同じ手順でデバッグを再現できます。

複数モジュール・マルチプロセスのデバッグ方法

大規模なPythonプロジェクトでは、複数のモジュールやプロセスが連携することがよくあります。

このような場合、単一のprogramを起動するだけでは全体の挙動が見えにくくなります。

VSCodeのPythonデバッガは、「launch」だけでなく「attach」モードもサポートしています。

attachモードを使うと、すでに起動しているPythonプロセスに後からデバッガを接続することができます。

設定例としては、次のような構成が考えられます。

JSONC
{
    "name": "Attach: Remote Worker",
    "type": "python",
    "request": "attach",
    "connect": {
        "host": "localhost",
        "port": 5678
    },
    "justMyCode": true
}

これと組み合わせて、worker側のPythonをdebugpyで起動します。

Shell
python -m debugpy --listen 5678 --wait-for-client worker.py

このように、1つのVSCodeから複数プロセスのデバッグを行うことで、プロセス間通信やサブプロセスの挙動も把握しやすくなります。

リモートコンテナやWSL上のPythonをデバッグする

近年では、PythonアプリケーションをコンテナやWSL上で動かすケースが増えています。

このような環境でも、VSCodeならローカルとほぼ同じ感覚でデバッグが可能です。

代表的な方法として、次の2つがあります。

1つ目はRemote - WSL拡張を使う方法です。

Windows上のVSCodeからWSL内のUbuntuに接続し、あたかもLinux上でVSCodeを動かしているかのように作業できます。

この状態でPython拡張をインストールすれば、WSL上のPython環境を直接デバッグできます。

2つ目はDev Containers拡張を使う方法です。

Dockerコンテナを開発用コンテナとしてVSCodeに接続し、その中にPythonや必要なライブラリをインストールします。

本番に近い環境をそのままデバッグ環境として利用できるため、環境差異によるバグを早期に発見できます。

いずれの場合も、launch.jsonの書き方は基本的に同じで、違いは「どの場所のファイルを開いているか」と「どのPythonインタプリタを選んでいるか」にあります。

VSCodeがリモート側のファイルシステムとプロセスに接続してくれるため、開発者はローカルとほぼ変わらない操作感でデバッグできます。

デバッグ設定とログ管理のベストプラクティス

VSCodeのデバッグ機能を日常的に使う際には、いくつかのベストプラクティスを意識しておくと、チーム開発でもスムーズに運用できます。

まず、launch.jsonは必ずバージョン管理に含めることを推奨します。

これにより、「どの引数でアプリケーションを起動するか」「どのモジュールをテストとして実行するか」といった情報を、チームの共通設定として共有できます。

次に、アプリケーション自体のログ管理も重要です。

Pythonのloggingモジュールを使い、ログレベル(INFO、DEBUGなど)や出力先(コンソール、ファイル)を設定しておくと、VSCodeのデバッガで観察する情報と、アプリケーション内部のログの両方からバグの原因を絞り込むことができます。

また、開発・ステージング・本番など複数環境を運用する際は、envFileenv設定を使って環境変数を切り替えられるようにしておくと便利です。

これにより、VSCode上から簡単に環境を変えつつ、同じデバッグ構成を流用できます。

最後に、チームでVSCodeを使う場合は、プロジェクトごとに推奨するPythonインタプリタとバージョンをREADMEなどに明記し、全員が同じ環境設定になるようにしておくと、デバッグ時の「動く・動かない」の差異を減らすことができます。

まとめ

VSCodeのPythonデバッガを活用すれば、print文に頼ることなく、プログラムの内部状態を自在に観察しながら開発を進められます。

ブレークポイントやステップ実行、変数ウォッチ、ログポイント、例外ブレークポイントなどを組み合わせることで、複雑なバグでも効率的に原因を特定できます。

さらに、launch.jsonによる構成管理や、リモート環境・テストとの連携を取り入れれば、個人開発だけでなくチーム開発でも強力な武器になります。

今日から少しずつVSCodeデバッガを使い始め、printデバッグからの卒業を目指してみてください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!