4

対話型セッション (私の場合ipython) 内で実行していて、現在デバッガー (ipdbまたはpdb) 内にいる場合、デバッグ名前空間内からメインの対話型名前空間に変数を配置できるようにしたいと考えています。

これは、コードがクラッシュするが、すでに重要な作業を行っており、そのうちのいくつかは時間を節約するために回収できる (たとえば、ディスクからデータをロードする) 場合に役立ちます。

だから私が欲しいのは、例えば次のようなものです:

>>> run -m my.module
loading data from disk...
done loading data.
processing data...
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
...

-> 処理中に問題が発生しましたが、データの読み込みは正常に行われました...そのため、デバッガーで何が起こったのかを確認し、以下を確認しますloaded_data

>>> debug
ipdb> len(loaded_data)
100000

->次に、この変数をインタラクティブな名前空間に保存して、デバッガーの外部で使用できるようにしたいと思います。次のようにします。

ipdb> save_to_interactive('loaded_data')
ipdb> exit
>>> len(loaded_data)
100000
4

1 に答える 1

8

これは、外部インタープリターのスタック フレームへの参照を取得し、そのフレーム グローバルに書き込むことで実現できます。

pdb に入るブレークポイントを持つサンプル モジュールがあるとします。

my_module.py :

def fun(arg):
    import pdb; pdb.set_trace()
    print arg

基本的な概念を示す例:

    >>> import my_module
    >>> my_module.fun(1)
    > /Users/lukasgraf/src/stackoverflow/my_module.py(3)fun()
    -> print arg
    (Pdb) import sys
    (Pdb) sys._getframe(0)
    <frame object at 0x1032ab290>
    # this is the current frame

    (Pdb) sys._getframe(0).f_globals['__name__']
    'my_module'

    # Next outer frame
    (Pdb) sys._getframe(1).f_globals['__name__']
    'pdb'

    # etc...

    # In this example, frame 10 happens to be
    # the one from the outer interpreter
    (Pdb) sys._getframe(10).f_globals['__name__']
    '__main__'

そこで、フレーム内グローバル'__name__'の値を探してスタックをさかのぼる手っ取り早い汚い関数を次に示します。'__main__'

debughelper.py :

import sys

# Be safe and define a maximum of frames we're trying to walk up
MAX_FRAMES = 20

def save_to_interactive(dct):
    n = 0
    # Walk up the stack looking for '__name__'
    # with a value of '__main__' in frame globals
    for n in range(MAX_FRAMES):
        cur_frame = sys._getframe(n)
        name = cur_frame.f_globals.get('__name__')
        if name == '__main__':
            # Yay - we're in the stack frame of the interactive interpreter!
            # So we update its frame globals with the dict containing our data
            cur_frame.f_globals.update(dct)
            break

使用法:

>>> import my_module
>>> my_module.fun('foo')
> /Users/lukasgraf/src/stackoverflow/my_module.py(3)fun()
-> print arg
(Pdb) import debughelper
(Pdb) debughelper.save_to_interactive({'mykey': 42})
(Pdb) c
foo
# We continued PDB, so we're in the outer interpreter again
>>> print mykey
42
>>>
于 2013-08-08T12:05:12.200 に答える