Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonデバッガー(pdb)の使い方を徹底解説!基本コマンドからブレークポイントまで

Pythonデバッガー(pdb)とは

ソフトウェア開発の分野では、プログラム内のエラー(バグ)を発見し修正するプロセスを「デバッグ」と呼びます。Pythonの標準ライブラリにはpdbモジュールが含まれており、これはPythonプログラムをデバッグするための一連のユーティリティを提供します。

デバッグ機能はPdbクラスとして定義されており、このモジュールは内部的にbdbおよびcmdモジュールを利用しています。

コマンドラインからの起動方法

pdbモジュールには非常に便利なコマンドラインインターフェースが用意されています。Pythonスクリプトの実行時に-mスイッチを使ってインポートすることで、デバッガーを起動できます。

python -m pdb script.py

サンプルコードで学ぶpdbの基本操作

デバッガーの動作を理解するために、まず次のようなPythonモジュール(fact.py)を作成してみましょう。階乗を計算するシンプルなプログラムです。

def fact(x):
    f = 1
    for i in range(1,x+1):
        print (i)
        f = f * i
    return f

if __name__=="__main__":
    print ("factorial of 3=",fact(3))

コマンドラインからこのモジュールのデバッグを開始すると、実行はコードの最初の行で停止します。停止した行の左側には矢印(->)が表示され、デバッガーのプロンプト(Pdb)が現れます。

C:\python36>python -m pdb fact.py
> c:\python36\fact.py(1)<module>()
-> def fact(x):
(Pdb)

ヘルプコマンドで使い方を確認

デバッガープロンプトに対して「help」と入力すると、すべてのデバッガーコマンドの一覧を表示できます。特定のコマンドについて詳しく知りたい場合は、「help <command>」という構文を使用します。

listコマンドでソースコードを表示

listコマンドを実行すると、プログラム全体のコードが表示され、現在プログラムが停止している行の左側に「->」記号が付きます。

(Pdb) list
1 -> def fact(x):
2     f = 1
3     for i in range(1,x+1):
4         print (i)
5         f = f * i
6     return f
7 if __name__=="__main__":
8     print ("factorial of 3 = ", fact(3))

stepとnext:行ごとの実行方法

プログラムを1行ずつ実行して進めるには、stepまたはnextコマンドを使用します。

(Pdb) step
> c:\python36\fact.py(7)<module>()
-> if __name__=="__main__":
(Pdb) next
> c:\python36\fact.py(8)<module>()
-> print ("factorial of 3 = ", fact(3))
(Pdb) next
1
2
3
factorial of 3= 6
--Return--
> c:\python36\fact.py(8)<module>()->None
-> print ("factorial of 3 = ", fact(3))

stepとnextの違い

stepnextの主な違いは以下の通りです。

  • step(s):関数の中に入り、その内部でプログラムを停止します
  • next(n):呼び出された関数を最後まで実行し、その後の行で停止します
C:\python36>python -m pdb fact.py
> c:\python36\fact.py(1)<module>()
-> def fact(x):
(Pdb) s
> c:\python36\fact.py(7)<module>()
-> if __name__=="__main__":
(Pdb) n
> c:\python36\fact.py(8)<module>()
-> print ("factorial of 3=",fact(3))
(Pdb) s
--Call--
> c:\python36\fact.py(1)fact()
-> def fact(x):
(Pdb) n
> c:\python36\fact.py(2)fact()
-> f = 1
(Pdb) n
> c:\python36\fact.py(3)fact()
-> for i in range(1,x+1):
(Pdb) n
> c:\python36\fact.py(4)fact()
-> print (i)
(Pdb) n
1
> c:\python36\fact.py(5)fact()
-> f = f * i
(Pdb) n
> c:\python36\fact.py(3)fact()
-> for i in range(1, x + 1):
(Pdb) n
> c:\python36\fact.py(4)fact()
-> print (i)
(Pdb) f,i
(1, 2)
(Pdb)

stepコマンドを使用すると、プログラムが関数呼び出しに遭遇した際に「--Call--」、関数が終了した際に「--Return--」という表示が現れます。また、任意の時点で変数名を入力するだけで、その変数の現在の値を確認できます。

breakコマンドによるブレークポイントの設定

プログラム内にブレークポイントを設定するには、breakコマンドを使用します。ブレークポイントを設定したい行番号を指定する必要があります。例えば「break 5」を実行すると、現在のプログラムの5行目にブレークポイントが設定されます。

(Pdb) list
2     f = 1
3     for i in range(1, x + 1):
4         print (i)
5         f = f * i
6     return f
7 -> if __name__=="__main__":
8     print ("factorial of 3=",fact(3))
[EOF]
(Pdb) break 5
Breakpoint 1 at c:\python36\fact.py:5
(Pdb) continue
1
> c:\python36\fact.py(5)fact()
-> f = f * i
(Pdb) break
Num Type Disp Enb Where
1 breakpoint keep yes at c:\python36\fact.py:5
breakpoint already hit 1 time
(Pdb) continue
2
> c:\python36\fact.py(5)fact()
-> f = f * i
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at c:\python36\fact.py:5
breakpoint already hit 2 times

continueコマンドを発行すると、プログラムの実行はブレークポイントに到達するまで続けられます。また、行番号を指定せずにbreakコマンドを実行するだけで、設定済みのすべてのブレークポイント一覧を表示できます。

ブレークポイントの無効化・有効化・削除

設定したブレークポイントは、disable/enableコマンドで無効化・有効化でき、clearコマンドで完全に削除することも可能です。

(Pdb) disable 1
Disabled breakpoint 1 at c:\python36\fact.py:5
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep no at c:\python36\fact.py:5
breakpoint already hit 2 times

スクリプト内からpdbを使う方法

Pdbデバッガーは、Pythonスクリプトの中から直接使用することもできます。その場合は、スクリプトの先頭でpdbをインポートし、プログラム内の任意の場所でset_trace()メソッドを呼び出します。

import pdb

def fact(x):
    f = 1
    for i in range(1,x+1):
        pdb.set_trace()
        print (i)
        f = f * i
    return f

if __name__=="__main__":
    print ("factorial of 3=",fact(3))

この方法で起動した場合も、デバッガーの動作はコマンドライン環境の場合とまったく同じになります。set_trace()を記述した位置で実行が一時停止し、これまで説明した各種コマンドを同じように使用できます。

まとめ

Python標準搭載のpdbデバッガーを使いこなすことで、print文を大量に埋め込むことなく、効率的にバグの原因を特定できるようになります。まずはstepnextbreakcontinueの4つのコマンドから覚えて、実際の開発に取り入れてみてください。

  1. JavaScriptのdebuggerステートメントの使い方を徹底解説

    JavaScriptのdebuggerステートメントは、コード内にブレークポイントを設定するための構文です。実行中のコードがdebuggerステートメントに到達すると、その時点で処理が一時停止し、開発者ツールのデバッガーが利用可能であれば自動的にデバッガー機能が呼び出されます。 debuggerステートメントの基本動作 debuggerステートメントは、以下のような場面で特に役立ちます。 コードの特定の箇所で処理を止めて、変数の値を確認したいとき ループ処理の各ステップを詳細に追跡したいとき 複雑なロジックの不具合原因を特定したいとき なお、ブラウザの開発者ツール(DevTools)が開い

  2. Pythonリストの内部動作を徹底解説!オブジェクトとフレームの仕組み

    このチュートリアルでは、Python 3.x(およびそれ以前のバージョン)におけるリストの内部動作について詳しく解説します。Pythonのステートメントを1行ずつ実行したときに、メモリ上でどのようにオブジェクトやフレームが形成されるのかを、図解を交えながら見ていきましょう。 リストの初期化 まずはリストの初期化です。これは、いくつかの要素を持つリストを作成することを意味します。 >>> lis=[1,2,3,4] 上図のように、リスト変数 lis はグローバルフレーム内で宣言され、リストオブジェクトへの参照(ポインタ)を保持しています。重要なのは、変数そのものがデータを格納