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 をケース毎に切替 |
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 にアタッチ が最終兵器:
-
kill -SIGUSR1 <pid>
→ コード内の signal ハンドラでpdb.set_trace()
- 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++
などのラッパーに乗り換えて、よりリッチな体験を試してみよう。