【问题标题】:save variable to interactive namespace from python debugger从 python 调试器将变量保存到交互式命名空间
【发布时间】:2013-08-08 11:00:42
【问题描述】:

当我在交互式会话中运行时(在我的情况下为 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

【问题讨论】:

  • 这不是 ipython 已经做的吗?如果不确定,请查看 locals()。

标签: python debugging namespaces


【解决方案1】:

您可以通过获取对外部解释器堆栈的引用来完成此操作 框架,并写入其框架全局变量。

给定一个带有断点的示例模块,将我们踢到 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
>>>

【讨论】:

  • 这真是太棒了,卢卡斯。真的非常感谢您:正是我想要的,完全解释和编程,而且如此之快!如果可以的话,我愿意给的不仅仅是一颗星。
  • 谢谢你的赞美,很高兴我能帮上忙:)
猜你喜欢
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2011-03-11
  • 2021-03-20
相关资源
最近更新 更多