pdb --- Python デバッガ

ソースコード: Lib/pdb.py


モジュール pdb は Python プログラム用の対話型ソースコードデバッガを定義します。 (条件付き)ブレークポイントの設定やソース行レベルでのシングルステップ実行、スタックフレームのインスペクション、ソースコードリスティングおよびあらゆるスタックフレームのコンテキストにおける任意の Python コードの評価をサポートしています。事後解析デバッギングもサポートし、プログラムの制御下で呼び出すことができます。

デバッガーは拡張可能です -- 実際にはクラス Pdb として定義されています。現在これについてのドキュメントはありませんが、ソースを読めば簡単に理解できます。拡張インターフェースはモジュール bdb と cmd を使っています。

参考

faulthandler モジュール

明示的な呼び出し時、障害発生時、タイムアウト後、またはユーザーシグナルの受信時に、Python のトレースバックを出力するために使います。

traceback モジュール

Python プログラムのスタックトレースを抽出・整形・表示する標準インターフェース。

デバッガに入る典型的な方法は、次のコードを挿入することです。

import pdb; pdb.set_trace()

もしくは:

breakpoint()

これをデバッガに入りたい位置に挿入し、プログラムを実行します。 この文の後に続くコードをステップ実行したり、continue コマンドでデバッガを使わずに実行を続けたりできます。

バージョン 3.7 で変更: 組み込み関数 breakpoint() をデフォルトの引数で呼び出すと、import pdb; pdb.set_trace() の代わりとして使えます。

def double(x):
   breakpoint()
   return x * 2
val = 3
print(f"{val} * 2 is {double(val)}")

デバッガのプロンプトは (Pdb) で、デバッグモードに入っていることを示します。

> ...(2)double()
-> breakpoint()
(Pdb) p x
3
(Pdb) continue
3 * 2 is 6

バージョン 3.3 で変更: readline モジュールによるコマンドおよびコマンド引数のタブ補完が利用できます。たとえば、p コマンドの引数では現在のグローバルおよびローカル名が候補として表示されます。

Command-line interface

You can also invoke pdb from the command line to debug other scripts. For example:

python -m pdb [-c command] (-m module | pyfile) [args ...]

モジュールとして pdb を起動すると、デバッグ中のプログラムが異常終了したときに pdb が自動的に事後デバッグモードに入ります。事後デバッグ後 (またはプログラムの正常終了後)、pdb はプログラムを再起動します。自動再起動を行った場合、pdb の状態 (ブレークポイントなど) はそのまま維持されるので、たいていの場合、プログラム終了時にデバッガーも終了させるよりも便利なはずです。

-c, --command <command>

.pdbrc ファイルで指定したかのようにコマンドを実行します。 Debugger commands を参照してください。

バージョン 3.2 で変更: -c オプションが追加されました。

-m <module>

python -m と同様の方法でモジュールを実行します。 スクリプトの場合と同様に、デバッガはモジュールの最初の行の直前で実行を一時停止します。

バージョン 3.7 で変更: -m オプションが追加されました。

デバッガの制御下で文を実行する典型的な使い方は次のとおりです。

>>> import pdb
>>> def f(x):
...     print(1 / x)
>>> pdb.run("f(2)")
> <string>(1)<module>()
(Pdb) continue
0.5
>>>

クラッシュしたプログラムを調べるための典型的な使い方は以下のようになります:

>>> import pdb
>>> def f(x):
...     print(1 / x)
...
>>> f(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
ZeroDivisionError: division by zero
>>> pdb.pm()
> <stdin>(2)f()
(Pdb) p x
0
(Pdb)

バージョン 3.13 で変更: PEP 667 の実装により、最適化されたスコープ 内での実行中であっても、pdb から名前に代入すると、実行中のスコープに直ちに反映されるようになりました。

このモジュールは以下の関数を定義しています。それぞれが少しづつ違った方法でデバッガに入ります:

pdb.run(statement, globals=None, locals=None)

デバッガーに制御された状態で (文字列またはコードオブジェクトとして与えられた) statement を実行します。あらゆるコードが実行される前にデバッガープロンプトが現れます。ブレークポイントを設定し、continue とタイプできます。あるいは、文を step や next を使って一つづつ実行することができます (これらのコマンドはすべて下で説明します)。オプションの globals と locals 引数はコードを実行する環境を指定します。デフォルトでは、モジュール __main__ の辞書が使われます。(組み込み関数 exec() または eval() の説明を参照してください。)

pdb.runeval(expression, globals=None, locals=None)

デバッガーに制御された状態で (文字列またはコードオブジェクトとして与えられる) expression を評価します。runeval() から復帰するとき、式の値を返します。その他の点では、この関数は run() と同様です。

pdb.runcall(function, *args, **kwds)

function (関数またはメソッドオブジェクト、文字列ではありません) を与えられた引数とともに呼び出します。 runcall() から復帰するとき、関数呼び出しが返したものはなんでも返します。関数に入るとすぐにデバッガプロンプトが現れます。

pdb.set_trace(*, header=None)

Enter the debugger at the calling stack frame. This is useful to hard-code a breakpoint at a given point in a program, even if the code is not otherwise being debugged (e.g. when an assertion fails). If given, header is printed to the console just before debugging begins.

バージョン 3.7 で変更: header キーワード専用引数。

バージョン 3.13 で変更: set_trace() は、次に実行されるコードの行を待たずに、直ちにデバッガに入るようになりました。

pdb.post_mortem(t=None)

指定された例外または トレースバックオブジェクト の事後デバッグに入ります。 値を指定しない場合は現在処理中の例外を使い、処理中の例外がなければ ValueError を送出します。

バージョン 3.13 で変更: 例外オブジェクトのサポートが追加されました。

pdb.pm()

sys.last_exc にある例外の事後デバッグに入ります。

run* 関数と set_trace() は、 Pdb クラスをインスタンス化して同名のメソッドを実行することのエイリアス関数です。それ以上の機能を利用したい場合は、インスタンス化を自分で行わなければなりません:

class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False, readrc=True)

Pdb はデバッガクラスです。

completekey, stdin, stdout 引数は、基底にある cmd.Cmd クラスに渡されます。そちらの解説を参照してください。

skip 引数が指定された場合、 glob スタイルのモジュール名パターンの iterable (イテレート可能オブジェクト) でなければなりません。デバッガはこのパターンのどれかにマッチするモジュールに属するフレームにはステップインしません。 [1]

デフォルトでは、Pdb は continue コマンドが投入されると、(ユーザーがコンソールから Ctrl-C を押したときに送られる) SIGINT シグナル用ハンドラーを設定します。これにより Ctrl-C を押すことで再度デバッガーを起動することができます。Pdb に SIGINT ハンドラーを変更させたくない場合は nosigint を true に設定してください。

readrc 引数はデフォルトでは真で、 Pdb が .pdbrc ファイルをファイルシステムから読み込むかどうかを制御します。

skip を使ってトレースする呼び出しの例:

import pdb; pdb.Pdb(skip=['django.*']).set_trace()

引数無しで 監査イベント pdb.Pdb を送出します。

バージョン 3.1 で変更: skip パラメータが追加されました。

バージョン 3.2 で変更: nosigint パラメータが追加されました。 以前は Pdb が SIGINT ハンドラを設定することはありませんでした。

バージョン 3.6 で変更: readrc 引数。

run(statement, globals=None, locals=None)
runeval(expression, globals=None, locals=None)
runcall(function, *args, **kwds)
set_trace()

前述のこれら関数のドキュメントを参照してください。

Debugger commands

デバッガーに認識されるコマンドは以下に一覧されています。たいていのコマンドは以下のように 1、2 文字に省略できます。例えば h(elp) は h か help がで help コマンドを呼び出すことを意味します (ただし he, hel, H, Help, HELP は使用できません)。コマンドの引数はホワイトスペース (スペースかタブ) で区切ってください。コマンド構文として任意の引数は大括弧 ([]) で括られています (実際に大括弧はタイプしないでください)。いくつかから選択できる引数は縦線 (|) で分割されて記述されています。

空行を入力すると入力された直前のコマンドを繰り返します。例外: 直前のコマンドが list コマンドならば、次の 11 行がリストされます。

デバッガが認識しないコマンドは Python 文とみなして、デバッグしているプログラムのコンテキストおいて実行されます。先頭にに感嘆符 (!) を付けることで Python 文であると明示することもできます。これはデバッグ中のプログラムを調査する強力な方法です。変数を変更したり関数を呼び出したりすることも可能です。このような文で例外が発生した場合には例外名が出力されますが、デバッガの状態は変化しません。

バージョン 3.13 で変更: 先頭部分が pdb のコマンドと一致する式や文を、正しく識別して実行できるようになりました。

デバッガは エイリアス をサポートしています。 エイリアスにはパラメータを持たせることができ、調査中のコンテキストにある程度合わせられます。

;; で区切ると、1 行に複数のコマンドを入力できます。 単一の ; は、Python パーサーに渡す 1 行の中で複数のコマンドを区切るために使うので、ここでは使いません。 コマンドの分割では構文を考慮せず、引用符で囲まれた文字列の途中であっても、最初の ;; で入力を分割します。 セミコロンが 2 つ連続する文字列を使うには、';'';' や ";"";" のように暗黙の文字列連結を使う方法があります。

一時的なグローバル変数を設定するには、簡易変数 (convenience variable) を使います。 簡易変数は、名前が $ で始まる変数です。 例えば、$foo = 1 はデバッガのセッションで使えるグローバル変数 $foo を設定します。 簡易変数 はプログラムの実行を再開すると消去されるため、foo = 1 のような通常の変数を使う場合よりも、プログラムに干渉する可能性が低くなります。

There are three preset convenience variables:

  • $_frame: 現在デバッグしているフレーム

  • $_retval: フレームが値を返す際の返り値

  • $_exception: フレームが例外を送出する際の例外

Added in version 3.12: 簡易変数 の機能が追加されました。

ユーザーのホームディレクトリまたはカレントディレクトリに .pdbrc ファイルがある場合、'utf-8' エンコーディングで読み込み、デバッガのプロンプトで入力したかのように実行します。 ただし、空行と # で始まる行は無視します。 この機能は特にエイリアスに便利です。 両方のファイルがある場合は、ホームディレクトリのファイルを先に読み込みます。 そこで定義されたエイリアスは、カレントディレクトリのファイルで上書きできます。

バージョン 3.2 で変更: .pdbrc に continue や next のようなデバッグを続行するコマンドが使用できるようになりました。以前はこのようなコマンドは無視されていました。

バージョン 3.11 で変更: .pdbrc を 'utf-8' エンコーディングで読むようになりました。 以前はシステムのロケールのエンコーディングで読んでいました。

h(elp) [command]

引数を指定しない場合、利用できるコマンドの一覧が表示されます。引数として command が与えられた場合、そのコマンドのヘルプが表示されます。help pdb で完全なドキュメント (pdb モジュールの doctring) が表示されます。command 引数は識別子でなければならないため、! コマンドのヘルプを表示するには help exec と入力します。

w(here)

Print a stack trace, with the most recent frame at the bottom. An arrow (>) indicates the current frame, which determines the context of most commands.

d(own) [count]

スタックフレーム内で現在のフレームを count レベル (デフォルトは 1) 新しいフレーム方向に移動します。

u(p) [count]

スタックフレーム内で現在のフレームを count レベル (デフォルトは 1) 古いフレーム方向に移動します。

b(reak) [([filename:]lineno | function) [, condition]]

With a lineno argument, set a break at line lineno in the current file. The line number may be prefixed with a filename and a colon, to specify a breakpoint in another file (possibly one that hasn't been loaded yet). The file is searched on sys.path. Accepatable forms of filename are /abspath/to/file.py, relpath/file.py, module and package.module.

function 引数を指定すると、その関数内の最初の実行可能な文にブレークポイントを設定します。 function は、現在の名前空間で評価すると関数になる任意の式にできます。

第二引数を指定する場合、その値は式で、その評価値が真でなければブレークポイントは有効になりません。

引数なしの場合は、それぞれのブレークポイントに対して、そのブレークポイントに行き当たった回数、現在の通過カウント ( ignore count ) と、もしあれば関連条件を含めてすべてのブレークポイントをリストします。

各ブレークポイントには番号が割り当てられます。 他のすべてのブレークポイントコマンドは、この番号でブレークポイントを参照します。

tbreak [([filename:]lineno | function) [, condition]]

一時的なブレークポイントで、最初にそこに達したときに自動的に取り除かれます。引数は break と同じです。

cl(ear) [filename:lineno | bpnumber ...]

filename:lineno 引数を与えると、その行にある全てのブレークポイントを解除します。スペースで区切られたブレークポイントナンバーのリストを与えると、それらのブレークポイントを解除します。引数なしの場合は、すべてのブレークポイントを解除します ( が、はじめに確認します ) 。

disable bpnumber [bpnumber ...]

空白で区切って指定した番号のブレークポイントを無効にします。 ブレークポイントを無効にすると、プログラムの実行を止めることができなくなりますが、ブレークポイントの解除と違いブレークポイントのリストに残っており、(再び) 有効にできます。

enable bpnumber [bpnumber ...]

指定したブレークポイントを有効にします。

ignore bpnumber [count]

与えられたブレークポイントナンバーに通過カウントを設定します。count が省略されると、通過カウントは 0 に設定されます。通過カウントがゼロになったとき、ブレークポイントが機能する状態になります。ゼロでないときは、そのブレークポイントが無効にされず、どんな関連条件も真に評価されていて、ブレークポイントに来るたびに count が減らされます。

condition bpnumber [condition]

ブレークポイントに新しい condition を設定します。condition はブレークポイントを制御する条件式で、この式が真を返す場合のみブレークポイントが有効になります。condition を指定しないと既存の条件が除去されます; ブレークポイントは常に有効になります。

commands [bpnumber]

ブレークポイントナンバー bpnumber にコマンドのリストを指定します。コマンドそのものはその後の行に続けます。end だけからなる行を入力することでコマンド群の終わりを示します。例を挙げます:

(Pdb) commands 1
(com) p some_variable
(com) end
(Pdb)

ブレークポイントからコマンドを取り除くには、 commands のあとに end だけを続けます。つまり、コマンドを一つも指定しないようにします。

bpnumber 引数を指定しない場合、commands は最後にセットしたブレークポイントを参照します。

ブレークポイントコマンドはプログラムを走らせ直すのに使えます。単に continue コマンドや step、その他実行を再開するコマンドを使えば良いのです。

Specifying any command resuming execution (currently continue, step, next, return, jump, quit and their abbreviations) terminates the command list (as if that command was immediately followed by end). This is because any time you resume execution (even with a simple next or step), you may encounter another breakpoint—which could have its own command list, leading to ambiguities about which list to execute.

If you use the silent command in the command list, the usual message about stopping at a breakpoint is not printed. This may be desirable for breakpoints that are to print a specific message and then continue. If none of the other commands print anything, you see no sign that the breakpoint was reached.

s(tep)

現在の行を実行し、最初に停止できる地点 (呼び出された関数の中、または現在の関数の次の行) で停止します。

n(ext)

現在の関数の次の行に達するか、あるいは関数が返るまで実行を継続します。 (next と step の差は step が呼び出された関数の内部で停止するのに対し、 next は呼び出された関数を (ほぼ) 全速力で実行し、現在の関数内の次の行で停止するだけです。)

unt(il) [lineno]

引数を省略すると、現在より大きい行番号の行に達するまで実行を続けます。

lineno を指定すると、番号が lineno 以上である行に到達するまで実行します。どちらにしても現在のフレームが返ってきた時点で停止します。

バージョン 3.2 で変更: 明示的に行数指定ができるようになりました。

r(eturn)

現在の関数が返るまで実行を継続します。

c(ont(inue))

ブレークポイントに出会うまで、実行を継続します。

j(ump) lineno

次に実行する行を指定します。最も底のフレーム中でのみ実行可能です。前に戻って実行したり、不要な部分をスキップして先の処理を実行する場合に使用します。

ジャンプには制限があり、例えば for ループの中には飛び込めませんし、 finally 節の外にも飛ぶ事ができません。

l(ist) [first[, last]]

現在のファイルのソースコードを表示します。引数を指定しないと、現在の行の前後 11 行分を表示するか、直前の表示を続行します。引数に . を指定すると、現在の行の前後 11 行分を表示します。数値を 1 個指定すると、その行番号の前後 11 行分を表示します。数値を 2 個指定すると、開始行と最終行として表示します; 2 個めの引数が 1 個め未満だった場合、1 個目を開始行、2 個めを開始行からの行数とみなします。

現在のフレーム内の現在の行は -> で表示されます。例外をデバッグ中の場合、例外が発生または伝搬した行は、それが現在の行とは異なるとき >> で表示されます。

バージョン 3.2 で変更: >> マーカーが追加されました。

ll | longlist

現在の関数またはフレームの全ソースコードを表示します。注目する行は list と同じようにマーカーがつきます。

Added in version 3.2.

a(rgs)

現在の関数の引数と、その現在の値を表示します。

p expression

現在のコンテキストにおいて expression を評価し、その値をプリントします。

注釈

print() も使えますが、これはデバッガーコマンドではありません --- これは Python の関数 print() が実行されます。

pp expression

p コマンドと同様ですが、expression の値を pprint モジュールで読みやすく整形して表示します。

whatis expression

expression の型を表示します。

source expression

expression のソースコードの取得を試み、可能であれば表示します。

Added in version 3.2.

display [expression]

現在のフレームで実行が停止するたびに expression の値を調べ、変化していれば表示します。

expression を指定しない場合、現在のフレームで表示対象として登録されているすべての式を表示します。

注釈

display は expression を評価し、前回の評価結果と比較します。 そのため、結果がミュータブルな場合は変更を検出できないことがあります。

以下はプログラム例です:

lst = []
breakpoint()
pass
lst.append(1)
print(lst)

比較する前に lst.append(1) が評価結果をその場で変更してしまうため、display は lst の変更を検出できません。

> example.py(3)<module>()
-> pass
(Pdb) display lst
display lst: []
(Pdb) n
> example.py(4)<module>()
-> lst.append(1)
(Pdb) n
> example.py(5)<module>()
-> print(lst)
(Pdb)

コピーの仕組みを使うと、変更を検出できるようになります。

> example.py(3)<module>()
-> pass
(Pdb) display lst[:]
display lst[:]: []
(Pdb) n
> example.py(4)<module>()
-> lst.append(1)
(Pdb) n
> example.py(5)<module>()
-> print(lst)
display lst[:]: [1]  [old: []]
(Pdb)

Added in version 3.2.

undisplay [expression]

現在のフレーム内で expression をこれ以上表示しないようにします。expression を指定しない場合、現在のフレームで display 指定されている式を全てクリアします。

Added in version 3.2.

interact

現在のスコープのローカル名前空間とグローバル名前空間から初期化した、新しいグローバル名前空間で、code モジュールを使って対話型インタープリタを開始します。 インタープリタを終了してデバッガに戻るには、exit() または quit() を使います。

注釈

interact はコード実行用に新しい専用の名前空間を作るため、変数への代入は元の名前空間に影響しません。 ただし、参照しているミュータブルなオブジェクトへの変更は、通常どおり元の名前空間にも反映されます。

Added in version 3.2.

バージョン 3.13 で変更: exit() と quit() で interact コマンドを終了できるようになりました。

バージョン 3.13 で変更: interact は sys.stderr ではなく、デバッガの出力先に出力するようになりました。

alias [name [command]]

command を実行する、name という名前のエイリアスを作ります。 command を引用符で囲んでは いけません。 置き換えるパラメータは %1、%2、...、%9 で指定でき、%* はすべてのパラメータに置き換えられます。 command を省略すると、name に対する現在のエイリアスを表示します。 引数を指定しない場合は、すべてのエイリアスを一覧表示します。

エイリアスは入れ子になってもよく、pdb プロンプトで合法的にタイプできるどんなものでも含めることができます。内部 pdb コマンドをエイリアスによって上書きすることが できます。そのとき、このようなコマンドはエイリアスが取り除かれるまで隠されます。エイリアス化はコマンド行の最初の語へ再帰的に適用されます。行の他のすべての語はそのままです。

例として、二つの便利なエイリアスがあります (特に .pdbrc ファイルに置かれたときに):

# インスタンス変数を表示する (使い方: "pi classInst")
alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")
# self のインスタンス変数を表示する
alias ps pi self
unalias name

指定したエイリアス name を削除します。

! statement

現在のスタックフレームのコンテキストで、1 行の statement を実行します。 文の最初の単語がデバッガコマンドに似ている場合を除き、感嘆符は省略できます。 例えば、次のようにします:

(Pdb) ! n=42
(Pdb)

グローバル変数を設定するには、代入の前に同じ行で global 文を指定できます。 例えば、次のようにします:

(Pdb) global list_options; list_options = ['-l']
(Pdb)
run [args ...]
restart [args ...]

デバッグ中の Python プログラムを再実行します。args が与えられると、 shlex で分割され、結果が新しい sys.argv として使われます。ヒストリー、ブレークポイント、アクション、そして、デバッガーオプションは引き継がれます。 restart は run の別名です。

q(uit)

Quit from the debugger. The program being executed is aborted.

debug code

code をステップ実行する、再帰的なデバッガに入ります。 code は現在の環境で実行する任意の式または文です。

retval

現在の関数の最後の return による返り値を表示します。

exceptions [excnumber]

連鎖した例外を一覧表示したり、例外間を移動したりします。

When using pdb.pm() or Pdb.post_mortem(...) with a chained exception instead of a traceback, it allows the user to move between the chained exceptions using exceptions command to list exceptions, and exceptions <number> to switch to that exception.

以下はプログラム例です:

def out():
    try:
        middle()
    except Exception as e:
        raise ValueError("reraise middle() error") from e

def middle():
    try:
        return inner(0)
    except Exception as e:
        raise ValueError("Middle fail")

def inner(x):
    1 / x

out()

pdb.pm() を呼び出すと、例外間を移動できます。

> example.py(5)out()
-> raise ValueError("reraise middle() error") from e

(Pdb) exceptions
  0 ZeroDivisionError('division by zero')
  1 ValueError('Middle fail')
> 2 ValueError('reraise middle() error')

(Pdb) exceptions 0
> example.py(16)inner()
-> 1 / x

(Pdb) up
> example.py(10)middle()
-> return inner(0)

Added in version 3.13.

脚注