Pythonのbreakpoint関数を使ってデバックの効率を高める方法

スポンサーリンク

Pythonでのデバッグは、開発者にとってそれなりの問題がありました。

一般的なデバッガとしては、pdbデバッガがありました。

しかし、セッションを解析するためには、次のようなことが必要になります。

import pdb
 
a = None
for i in range(10):
    if i == 4:
        a = 'Hi'
        print('a is set to', a)
    elif i == 5:
        pdb.set_trace()

結果は以下の通りです。

a is set to Hi
> d:userpdb-tut.py(4)<module>()
-> for i in range(10):
(Pdb) p a
'Hi'
(Pdb)

pdb.set_trace()` を使えば、環境の内容と関連するすべての変数を取得できますが、デバッグを行う必要があるたびにこれを挿入するのは非常に時間がかかることがよくあります。

さらに、デバッグが必要なたびにモジュールをインポートすることは、すべての開発者にとって直感的なことではありません。

Python 3.7では、breakpoint()メソッドが導入され、 pdb をインポートして pdb.set_trace() を呼び出すという作業が行われるようになりました。

したがって、 breakpoint() を呼び出すと、pdbセッションが生成されます。

スポンサーリンク

breakpoint() について

breakpoint()関数はsysモジュールのsys.breakpointhook()という別のメソッドを呼び出し、pdb` セッションへの入力を行います。

このメソッドのシグネチャは breakpoint(*args, **kwargs) です。

位置引数とキーワード引数は sys.breakpointhook() に渡されますが、シグネチャが一致しない場合は TypeError を発生させる可能性があります。

以下の例では、breakpoint() がどのように使用されるかを示しています。

a = []
 
for i in range(10):
    a.append(i)
    if i == 6:
        # Start pdb instance when i = 6
        breakpoint()
 
print(a)

結果は以下の通りです。

> user/askpython/breakpoint_example.py(3)<module>()
-> for i in range(10):
(Pdb) p a
[0, 1, 2, 3, 4, 5, 6]
(Pdb) n
> user/askpython/breakpoint_example.py(4)<module>()
-> a.append(i)
(Pdb) p a
[0, 1, 2, 3, 4, 5, 6]
(Pdb) n
> user/askpython/breakpoint_example.py(5)<module>()
-> if i == 6:
(Pdb) n
> user/askpython/breakpoint_example.py(3)<module>()
-> for i in range(10):
(Pdb) n
> user/askpython/breakpoint_example.py(4)<module>()
-> a.append(i)
(Pdb) n
> user/askpython/breakpoint_example.py(5)<module>()
-> if i == 6:
(Pdb)
> user/askpython/breakpoint_example.py(3)<module>()
-> for i in range(10):
(Pdb)
> user/askpython/breakpoint_example.py(4)<module>()
-> a.append(i)
(Pdb)
> user/askpython/breakpoint_example.py(5)<module>()
-> if i == 6:
(Pdb)
> user/askpython/breakpoint_example.py(3)<module>()
-> for i in range(10):
(Pdb)
> user/askpython/breakpoint_example.py(8)<module>()
-> print(a)
(Pdb)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
--Return--

PYTHONBREAKPOINT 環境変数

sys.pythonbreakpointhook()は環境変数PYTHONBREAKPOINTを使用します。

この変数を0または無効にすると、breakpoint()が呼ばれたときにpdb` デバッガを使用しないので、デバッガを無効にすることができます

その結果、この環境変数を用いて、デバッグモードを切り替えることができる。

そのため、コード中にブレークポイントがあるが、デバッグモードに移行したくない場合は、Pythonプログラムを実行する際に、この環境変数の設定を解除するだけでよいのです。

root@Ubuntu $ PYTHONBREAKPOINT=0 python breakpoint_example.py

結果は以下の通りです。

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Change debugging sessions

環境変数 PYTHONBREAKPOINT は、pdb 以外の様々なサードパーティデバッガを使用してデバッグを行うために使用することができます

この変数を使用して、 web-pdbpudb などのサードパーティデバッグセッションを開始する callable の名前を設定することができる。

これらを使いたい場合は、以下のようにしてインストールすることができる。

pip3 install pudb
pip3 install web-pdb

以下の例では、breakpoint() コールを使用して pudb デバッグセッションと統合しています。

root@Ubuntu $ PYTHONBREAKPOINT=pudb.set_trace python3 breakpoint_example.py

結果は以下の通りです。

root@Ubuntu $ PYTHONBREAKPOINT=web_pdb.set_trace python3 breakpoint_example.py
2019-12-28 14:52:55,398: root - web_console:108 - CRITICAL - Web-PDB: starting web-server on root-pc:5555...

同様に、web-pdb セッションも以下のコマンドで開始することができます

Pudb Debugger
A Pudb Debugging Session

出力 (localhost:5555 の場合)

Web Pdb Debugger 1
A Web Pdb Debugger Session

まとめ

デバッグのために使われる Python の breakpoint() 関数と、他のサードパーティデバッガーを使って様々なデバッグセッションを開始するために使用できる環境変数 PYTHONBREAKPOINT について学びました。

参考文献

  • Python breakpoint() ドキュメント
  • breakpoint() に関する JournalDev の記事。
タイトルとURLをコピーしました