LoginSignup
4
7

More than 1 year has passed since last update.

【Python】pdb/ipdb/pdb++でデバッグをより効率的に!

Last updated at Posted at 2020-07-28

はじめに

プログラムのデバッグによく使うのがprint()があるが、pdbを使えばもっと効率よくできるそうなのでメモ

pdbとは?

本記事では,はじめにpdbの使い方を説明した後,ipdbやpdb++についても簡単に説明します.

pdbの使い方

はじめにpdbの使い方について説明していきます.

基本

以下のようなスクリプトを準備します.

  • mymodule.py
    • test(): Hello Worldを5つprintする関数
mymodule.py
def test():
    print("Hello World1")
    print("Hello World2")
    print("Hello World3")
    print("Hello World4")
    print("Hello World5")
  • main.py
    • mymoduleをimportするスクリプト
main.py
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の途中に入れてみます.

mymodule.py
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を以下のように変更したとします.

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++について紹介しました.どのライブラリを使うかは個人の好みでいいかと思いますが,(自分も含めて)これらのツールを使ってより効率的に開発を進めていきたいですね!

4
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7