pythonスクリプトをデバッグしています。gdbでメモリアドレスを監視できるように、変数を監視したいのですが、これを行う方法はありますか?
ブレークポイントをヒットしているときに変数を監視するには、commands
コマンドを使用できます。例えば。印刷some_variable
ブレークポイント#1にヒットしたとき( pdb
docの標準的な例 )。
(Pdb) commands 1
(com) print some_variable
(com) end
(Pdb)
Python 3の更新
(Pdb) commands 1
(com) print(some_variable)
(com) end
(Pdb)
また、condition
コマンドを使用して、変数が特定の値をとるときにのみブレークポイントにヒットするようにすることができます。
例えば:
(Pdb) condition 1 some_variable==some_value
pdb
を使用してこれを行うための非常にハックな方法を次に示します。これらのコマンドは、~/.pdbrc
pdb
を使用するたびに自動的にロードします。
!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack
!global __copy; from copy import copy as __copy
!global __Pdb; from pdb import Pdb as __Pdb
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1]
alias _setup_watchpoint !global __key, __dict, __val; __key = '%1'; __dict = __currentframe().f_locals if __currentframe().f_locals.has_key(__key) else __currentframe().f_globals; __val = __copy(%1)
alias _nextwatch_internal next;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_nextwatch_internal %1")
alias _stepwatch_internal step;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_stepwatch_internal %1")
alias nextwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_nextwatch_internal"])
alias stepwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_stepwatch_internal"])
これにより、nextwatch
とstepwatch
の2つのコマンドが追加されます。これらはそれぞれ変数名varnameを引数として取ります。可能であればvarnameの現在のフレームのローカル変数の浅いコピーを作成し、その名前が指すものが変更されるまでnext
またはstep
をそれぞれ実行し続けます。
これはCPython 2.7.2で動作しますが、いくつかのpdb
内部に依存しているため、おそらく他の場所で壊れます。
Python 3の場合:
使用できます表示pdbの機能
ブレークポイントに到達したら、単に入力します
ipdb>displayexpression
例:
ipdb> display instance
display instance: <AppUser: dmitry4>
ipdb> display instance.id
display instance.id: 9
ipdb> display instance.university
display instance.university: <University: @domain.com>
ipdb> display
Currently displaying:
instance.university: <University: @domain.com>
instance.id: 9
instance: <AppUser: dmitry4>
ipdb>
ご覧のとおり、ディスプレイを入力するたびに、すべてのウォッチ(式)が出力されます。組み込み関数undisplay
を使用して、特定のウォッチを削除できます。
pp expressionを使用して、式をきれいに印刷することもできます(非常に便利です)
可能な解決策は、 pdb ++ を使用することです。
_pip install pdbpp
_
次に、デコレータ_@pdb.break_on_setattr
_を使用して、監視するオブジェクトを「マーク」します。
_from pdb import break_on_setattr
@break_on_setattr('bar')
class Foo(object):
pass
f = Foo()
f.bar = 42 # the program breaks here
_
ここで、pdb
は、Fooオブジェクトの属性bar
を変更すると中断します。
注意事項
基礎となる___setattr__
_- methodの呼び出しのみがブレークポイントをトリガーします。これは、_f.bar = 'XYZ'
_およびsetattr(f, 'XYZ')
は機能するが、bar
-オブジェクトを操作してもブレークポイントがトリガーされないことを意味します。
_f.bar = []
f.bar.append(7) # will NOT trigger breakpoint
f.bar = 2
f.bar += 5 # will trigger breakpoint
_
注:_@break_on_setattr
_は、標準のpdb
- moduleの一部ではありません。 pdb
は、pdbpp
- packageによってオーバーライド/モンキーパッチされます。
pdb.set_trace()
の後に、既存のオブジェクトを(そのクラスを介して)ラップすることもできます。
_(Pdb++) import pdb
(Pdb++) pdb.break_on_setattr('tree_id')(self.__class__)
(Pdb++) continue
_