はじめに
プログラムのデバッグによく使うのがprint()
があるが、pdb
を使えばもっと効率よくできるそうなのでメモ
pdbとは?
-
pdbとはpython標準ライブラリの名称でpython用ソースコードデバッガです.
- 公式ドキュメント: pdb --Pythonデバッガ
- 基本的にはpdbを使うことで十分デバッグ可能ですが,独自に拡張したい際には
Pdb
の継承クラスを定義することで拡張可能です.
-
またpdbの拡張版として
ipdb
やpdb++
があります
本記事では,はじめにpdbの使い方を説明した後,ipdbやpdb++についても簡単に説明します.
pdbの使い方
はじめにpdbの使い方について説明していきます.
基本
以下のようなスクリプトを準備します.
-
mymodule.py
-
test()
: Hello Worldを5つprintする関数
-
def test():
print("Hello World1")
print("Hello World2")
print("Hello World3")
print("Hello World4")
print("Hello World5")
-
main.py
- mymoduleをimportするスクリプト
import gdb
import mymodule
pdb.run("mymodule.test()")
main.py
内でデバッグしたいモジュールをpdb.run()
に渡すことでデバッグが実行できます.
これで実行してみます.実行すると
$ python3 main.py
> <string>(1)<module>()
(Pdb)
となるので,continue
または c
と入力すればデバッグが実行されます.
今回はバグやブレイクポイントを置いて無いのでただprint()が行われるだけです.
$ python3 main.py
> <string>(1)<module>()
(Pdb) continue # または c
Hello World1
Hello World2
Hello World3
Hello World4
Hello World5
ブレイクポイントを挿入
デバッグを行いたいポイントにpdb.set_trace()
を書き込むことでブレイクポイントを挿入できます.
試しに先程のmymodule.py
のprintの途中に入れてみます.
import pdb
def test():
print("Hello World1")
print("Hello World2")
print("Hello World3")
pdb.set_trace()
print("Hello World4")
print("Hello World5")
これでmain.py
を実行してみます.すると3つ目のprint("Hello World3)
の実行後,処理が一時停止しているのが分かります.
$ python3 main.py
> <string>(1)<module>()
(Pdb) c
Hello World1
Hello World2
Hello World3
> /home/ktro2828/my_package/mymodule.py(9)test()
-> print("Hello World4")
(Pdb) c # 一時停止後,再実行
Hello World4
Hello World5
一時停止後,以下のコマンドを使えば1行づつの実行なども可能です.
コマンド | 表 |
---|---|
s (step) | 現在の行を実行 |
n (next) | 現在の関数の次の行に達するか,関数が返るまで実行を継続 |
unt(il) | 行数を指定すると,指定行数かそれ以上に達するまで実行.引数なしだとstepと同じ |
r (return) | 現在の関数が返るまで実行を継続 |
l (list) | 現在のファイルのソースコードを表示.引数を指定しないと,現在の行の前後11行分を表示 |
a (args) | 現在の関数の引数を表示 |
p | 現在のコンテキストにおいてexpressionを評価し,結果をプリント |
c (cont(inue)) | 次のブレイクポイントまで実行 |
挿入なしでデバッグ
- 上のようにいちいちブレイクポイントを挿入しなくてもデバッグ可能です.
$ python -m pdb <スクリプト名>
(@shiracamusさんありがとうございます。)
ipdbについて
次にipdbについて説明します.といっても使い方自体はpdbとほとんど変わりません.
ipdbはpdbと違い,標準ライブラリではないので別途インストールが必要です.
$ pip install ipdb
- ipdbとpdbの違いとしては以下が挙げられます
1. デバッガのデザインに色がついている
ipdbではデバッガに色がつけられ,pdbに比べて見やすくなっています.
2. タブ補完が効く
ipdbではタブ補完によって候補を表示してくれます.
3. コマンドが増える
ipdbではpdbで使用可能なコマンドに加えて使えるコマンドが増えています
詳細については,
ipdb> h
Documented commands (type help <topic>):
========================================
EOF clear display l pfile return tbreak where
a commands down list pinfo retval u
alias condition enable ll pinfo2 run unalias
args cont exit longlist pp rv undisplay
b context h n psource s unt
break continue help next q skip_hidden until
bt d ignore p quit skip_predicates up
c debug j pdef r source w
cl disable jump pdoc restart step whatis
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
interact
コマンドの詳細を確認したいときは以下で確認できます.
ipdb> help <COMANND>
pdb++について
最後にpdb++についてです.
pdb++もipdb同様別途インストールが必要です.
$ pip install pdbpp
pdb++はインストールするとpdbを置き換えてくれるので使用する際は,import pdb
のままで使うことができます.
pdb++をインストールした後,最初に示した例を実行すると以下のようにデバッガが色づけられ,(Pdb)
-> (Pdb++)
になっていることが確認できます.
- pdb++ではipdbに加えて以下の特徴が挙げられます
1. コマンドが増える
(Pdb++) help
Documented commands (type help <topic>):
========================================
EOF cl disable help list quit step until
a clear display hf_hide ll r sticky up
alias commands down hf_unhide longlist restart tbreak w
args condition ed ignore n return track whatis
b cont edit interact next retval u where
break continue enable j p run unalias
bt d exit jump pp rv undisplay
c debug h l q s unt
Miscellaneous help topics:
==========================
exec hidden_frames pdb
Undocumented commands:
======================
f frame hf_list inspect paste put source
詳細については,
(Pdb++) help <COMMAND>
やGitHubリポジトリを参照してください.
2. コマンドパーサーが賢い
pdb++では,コマンドと変数
例えば,mymodule.py
を以下のように変更したとします.
import pdb
def test():
c = 10
print("Hello World1")
print("Hello World2")
print("Hello World3")
print("Hello World4")
print("Hello World5")
print(f"c = {c}")
pdb.set_trace()
return c
pdbの場合では,ブレークポイント後c(continue)
を押すとそのまま処理が実行されますが,pdb++では変数cの値を返してくれます.
再びcontinueを実行したい場合は!!c
で処理を再実行します.
$ python3 main.py
[1] > <string>(1)<module>()
(Pdb++) c
Hello World1
Hello World2
Hello World3
Hello World4
Hello World5
c = 10
[4] > /home/ktro2828/my_project/my_project/mymodule.py(13)test()
-> return c
(Pdb++) c
10
(Pdb++) c
10
(Pdb++) !!c # !!cでcontinueを実行
おわりに
今回は,python標準デバッガであるpdbとその拡張版であるipdb/pdb++について紹介しました.どのライブラリを使うかは個人の好みでいいかと思いますが,(自分も含めて)これらのツールを使ってより効率的に開発を進めていきたいですね!