27.3. pdb — Python デバッガ

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


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

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

デバッガのプロンプトは (Pdb) です。デバッガに制御された状態でプログラムを実行するための典型的な使い方は以下のようになります:

>>> import pdb
>>> import mymodule
>>> pdb.run('mymodule.test()')
> <string>(0)?()
(Pdb) continue
> <string>(1)?()
(Pdb) continue
NameError: 'spam'
> <string>(1)?()
(Pdb)

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

他のスクリプトをデバッグするために、 pdb.py をスクリプトとして呼び出すこともできます。例えば:

python3 -m pdb myscript.py

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

バージョン 3.2 で追加: pdb.py-c オプションを受け付けるようになりました。このオプションで .pdbrc ファイルが与えられると、ファイル内のコマンドを実行します。デバッガコマンド を参照してください。

実行するプログラムをデバッガで分析する典型的な使い方は:

import pdb; pdb.set_trace()

これでコードの中のその後に続く文をステップ実行できます。そして continue コマンドでデバッガーを停止し処理を続行できます。

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

>>> import pdb
>>> import mymodule
>>> mymodule.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "./mymodule.py", line 4, in test
    test2()
  File "./mymodule.py", line 3, in test2
    print(spam)
NameError: spam
>>> pdb.pm()
> ./mymodule.py(3)test2()
-> print(spam)
(Pdb)

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

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

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

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

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

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

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

pdb.set_trace()

スタックフレームを呼び出したところでデバッガに入ります。たとえコードが別の方法でデバッグされている最中でなくても (例えば、アサーションが失敗するとき)、これはプログラムの所定の場所でブレークポイントをハードコードするために役に立ちます。

pdb.post_mortem(traceback=None)

与えられた traceback オブジェクトの事後解析デバッギングに入ります。もし traceback が与えられなければ、その時点で取り扱っている例外のうちのひとつを使います。 (デフォルト動作をさせるには、例外を取り扱っている最中である必要があります。)

pdb.pm()

sys.last_traceback のトレースバックの事後解析デバッギングに入ります。

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 に設定してください。

The readrc argument defaults to true and controls whether Pdb will load .pdbrc files from the filesystem.

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

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

バージョン 3.1 で追加: skip 引数が追加されました。

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

バージョン 3.6 で変更: The readrc argument.

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

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

27.3.1. デバッガコマンド

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

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

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

デバッガーは エイリアス をサポートしています。エイリアスはデバッグ中のコンテキストに適用可能な一定レベルのパラメーターを保持することができます。

複数のコマンドを ;; で区切って一行で入力することができます。(一つだけの ; では使用できません。なぜなら、Python パーサーへ渡される行内の複数のコマンドのための分離記号だからです。) コマンドを分割するために何も知的なことはしていません。たとえ引用文字列の途中であっても、入力は最初の ;; で分割されます。

ファイル .pdbrc がユーザーのホームディレクトリかカレントディレクトリにあれば、それが読み込まれ、デバッガーのプロンプトでタイプしたように実行されます。これは特にエイリアスを使用するときに役立ちます。両方にファイルが存在する場合、ホームディレクトリのものが最初に読まれ、次にカレントディレクトリにあるものが読み込まれます。後者により前者の定義は上書きされます。

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

h(elp) [command]

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

w(here)

スタックの底にある最も新しいフレームと一緒にスタックトレースをプリントします。矢印はカレントフレームを指し、それがほとんどのコマンドのコンテキストを決定します。

d(own) [count]

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

u(p) [count]

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

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

lineno 引数を指定した場合、現在のファイルのその行番号の場所にブレークポイントを設定します。function 引数を指定した場合、その関数の中の最初の実行可能文にブレークポイントを設定します。別のファイル (まだロードされていないかもしれないもの) のブレークポイントを指定するには、行番号の前にファイル名とコロンを付けます。ファイルは sys.path にそって検索されます。各ブレークポイントには番号が割り当てられ、その番号を他のすべてのブレークポイントコマンドで参照されることに注意してください。

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

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

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

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

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

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

disable [bpnumber [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 引数が指定されない場合、最後にセットされたブレークポイントを参照することになります。

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

実行を再開するコマンド (現在のところ continue, step, next, return, jump, quit とそれらの省略形) によって、コマンドリストは終了するものと見なされます (コマンドにすぐ end が続いているかのように)。というのも実行を再開すれば (それが単純な next や step であっても) 別のブレークポイントに到達するかもしれないからです。そのブレークポイントにさらにコマンドリストがあれば、どちらのリストを実行すべきか状況が曖昧になります。

コマンドリストの中で ‘silent’ コマンドを使うと、ブレークポイントで停止したという通常のメッセージはプリントされません。この振る舞いは特定のメッセージを出して実行を続けるようなブレークポイントでは望ましいものでしょう。他のコマンドが何も画面出力をしなければ、そのブレークポイントに到達したというサインを見ないことになります。

s(tep)

現在の行を実行し、最初に実行可能なものがあらわれたときに (呼び出された関数の中か、現在の関数の次の行で) 停止します。

n(ext)

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

unt(il) [lineno]

引数なしだと、現在の行から 1 行先まで実行します。

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

バージョン 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 と同じようにマーカーがつきます。

バージョン 3.2 で追加.

a(rgs)

現在の関数の引数リストをプリントします。

p expression

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

注釈

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

pp expression

p コマンドに似ていますが、式の値以外は pprint モジュールを使用して “pretty-print” されます。

whatis expression

式の型を表示します。

source expression

与えられたオブジェクトのソースコードの取得を試み、可能であれば表示します。

バージョン 3.2 で追加.

display [expression]

式の値が変更されていれば表示します。毎回実行は現在のフレームで停止します。

式を指定しない場合、現在のフレームのすべての式を表示します。

バージョン 3.2 で追加.

undisplay [expression]

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

バージョン 3.2 で追加.

interact

対話型インタープリターを (code モジュールを使って) 開始します。グローバル名前空間には現在のスコープで見つかったすべてのグローバルおよびローカル名が含まれます。

バージョン 3.2 で追加.

alias [name [command]]

name という名前の command を実行するエイリアスを作成します。コマンドは引用符で囲まれていては いけません。入れ替え可能なパラメーターは %1%2 などで指し示され、さらに %* は全パラメーターに置き換えられます。コマンドが与えられなければ、name に対する現在のエイリアスを表示します。引数が与えられなければ、すべてのエイリアスがリストされます。

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

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

# Print instance variables (usage "pi classInst")
alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])
# Print instance variables in self
alias ps pi self
unalias name

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

! statement

現在のスタックフレームのコンテキストにおいて(一行の) statement を実行します。文の最初の語がデバッガーコマンドと共通でない場合は、感嘆符を省略することができます。グローバル変数を設定するために、同じ行に global 文とともに代入コマンドの前に付けることができます。:

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

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

q(uit)

デバッガーを終了します。実行しているプログラムは中断されます。

脚注

[1]

フレームが属するモジュールは、そのフレームのグローバルの __name__ によって決定されます。