#0170（2025/06/15）Python標準デバッガ pdb 徹底入門 

# Python標準デバッガ pdb 徹底入門 


## 1. はじめに

* Python を日常的に書くエンジニアであれば、**pdb** は避けて通れない“最後のルーペ”。
* IDE デバッガで事足りる場面も多いが、SSH 先や CI、Docker コンテナ内部など **GUI に頼れない環境** では pdb が生命線となる。
* 本稿では「操作方法は知っている」前提で、その **応用テクニック・落とし穴・運用ノウハウ** を 3000 字弱で凝縮する。

## 2. 起動パターンを使い分ける

* **モジュール起動**: `python -m pdb my_script.py`
  ↳ 例外が出た瞬間にフレームに入る。ワンショット解析に便利。
* **インライン停止**: `import pdb; pdb.set_trace()`
  ↳ 調べたい位置をピンポイントで止められる。Git への混入注意。
* **breakpoint() API** (Py3.7+)
  ↳ `PYTHONBREAKPOINT=0` で無効化できるため、本番に残しても安全。ただしロギング→ pbd 起動など **hook 関数** を差し替える運用に慣れておくと真価を発揮する。

## 3. 基本 & 応用コマンド速習表

### 🔰 基本コマンド

| コマンド       | 動作                     | 補足/使いどころ             |
| ---------- | ---------------------- | -------------------- |
| `n`        | 同一フレームで次行へ進む           | ループをサクッと流すときに便利      |
| `s`        | 次の実行行へステップイン           | 関数内部のロジックを詳しく追跡      |
| `c`        | 次のブレークポイント／プログラム終了まで継続 | 調査箇所だけ止めたいとき         |
| `r`        | 現在の関数を最後まで実行し呼び出し元へ戻る  | 戻り値を素早く確認したい場合       |
| `l`        | 現在位置周辺のソースを表示          | コードの文脈把握             |
| `p <expr>` | 式を評価して表示               | `p my_var` で変数チェック   |
| `a`        | 現在フレームの引数を列挙           | signature を読みに行く手間削減 |
| `q`        | デバッガを終了してプログラムも停止      | 調査を切り上げる時            |

### 🚀 応用コマンド（中上級者向け）

| コマンド                      | 動作                  | 代表的ユースケース                 |
| ------------------------- | ------------------- | ------------------------- |
| `d` / `u`                 | down / up：コールスタック移動 | 深い再帰・多段呼び出しのトレース          |
| `! <expr>`                | 任意の Python を実行      | 変数値を書き換えて動作を確認            |
| `display <expr>`          | ステップ毎に expr の値を自動表示 | ループ内での変化を監視               |
| `b <loc>, <cond>`         | 条件付きブレークポイント        | 巨大ループで条件一致時のみ停止           |
| `ignore <bp> <n>`         | ブレークポイントを n 回無視     | 初期数回をスキップして効率化            |
| `enable` / `disable` <bp> | BP の一時無効化／有効化       | 大量 BP をケース毎に切替            |
| `interact`                | IPython シェルへ切り替え    | 補完・履歴がほしいとき（IPython 環境のみ） |
| `pp <expr>`               | `pprint` で整形出力      | ネスト構造や JSON を読みやすく        |

## 4. 条件付きブレークポイントの極意. 条件付きブレークポイントの極意

* `"b <file>:<lineno>, <cond>"` で **値が揃う瞬間だけ** 止める。ループ 10 万回でも高速。
* `break myfunc if retries > 5` と関数名指定も OK。大規模コードで行番号を気にしない運用がラク。
* 大量に張ったら `disable 1 3` / `enable 1-10` で **一時停止・再開** を制御し、`ignore` で **命中回数をスキップ** できる。

## 5. 例外調査：ポストモーテム & pytest 連携

* **ポストモーテム**: `pdb.pm()` を except 節で呼び出すと、クラッシュ地点で即シェルへ。
* **pytest**: `pytest -x --pdb` で失敗テストのスタックに飛び込み、`--pdbcls=IPython.terminal.debugger:TerminalPdb` で IPython ベースへ拡張可。

## 6. 非同期・並列コードを捉える

* `asyncio` ではイベントループが `set_trace()` に奪われるため **一時的に loop.stop()** してからステップ。
* **trio** / **curio** は `trio._tools.DEV_MODE = True` でデバッガフレンドリに。
* **multiprocessing**: 子プロセスで `pdb.set_trace()` すると標準入力が競合。`python -m pdb -c continue -m your.module` で **親側からアタッチ** する戦略も覚えておく。

## 7. リモートデバッグ & tmux 併用

* ポートフォワード不可の環境では **tmux split + pid にアタッチ** が最終兵器：

  1. `kill -SIGUSR1 <pid>` → コード内の signal ハンドラで `pdb.set_trace()`
  2. tmux の別ペインで標準入力を共有して操作。
* オープンソースなら `pdb_attach` パッケージを使うと `telnet localhost 4444` で接続できてスマート。

## 8. カスタマイズ：.pdbrc と subclassing

* ホームに `.pdbrc` を置くと起動時に自動実行。以下サンプル：

  ```
  # ~/.pdbrc
  alias ls !print('\n'.join(sorted(globals().keys())))
  alias wt where
  ```

  ↳ **独自エイリアスでタイプ数を劇的削減**。
* より踏み込むなら `class MyPdb(pdb.Pdb): …` でメソッドを拡張。例：`do_pp` を上書きして **pretty‑print** など。

## 9. 実戦投入のベストプラクティス

* **無闇な set\_trace() → git add** は厳禁。pre‑commit で `DEBUGGER` トークン検索を自動化し事故防止。
* ロングラン処理では `if DEBUG: breakpoint()` で **環境変数フラグ** をトリガとする設計が安全。
* デバッグ不能な本番障害に備え、**Sentry + pdb.pm()** で本番コアを即時調査するパターンも検討。

## 10. まとめ

* pdb は「動く教科書」。IDE の快適さは無いものの、**最低限の I/O さえあればどこでも同じ体験を提供** する。
* 時間短縮の鍵は「操作を体で覚える」こと。`n s c r` をブラインドタッチし、`.pdbrc` で指の移動量を減らせば更に捗る。
* **breakpoint() + CI** で落下点を再現し、`pytest --pdb` でテスト失敗を即対話する──これが現代 Python デバッグの黄金パス。

> **次の一歩** : IPython 統合版 `ipdb` や GUI 連携、`pdb++` などのラッパーに乗り換えて、よりリッチな体験を試してみよう。

---