从 python 调试器将变量保存到交互式命名空间

时间:2023-05-13
本文介绍了从 python 调试器将变量保存到交互式命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

限时送ChatGPT账号..

当我在交互式会话中运行时(在我的例子中是 ipython),并且当前在调试器中(ipdbpdb)我希望能够从调试命名空间中将变量放入主交互式命名空间.

When I am running inside an interactive session (in my case ipython), and am currently inside a debugger (ipdb or pdb) I would like to be able to put a variable into the main interactive namespace from within the debugging namespace.

这在我的代码崩溃但已经完成大量工作时很有用,其中一些可以挽救以节省时间(例如,从磁盘加载数据).

This is useful if my code crashes, but has already done significant work, some of which is salvageable to save time (for example, loading data from disk).

所以我想要的是这样的,例如:

so what I'd like is something like this, for example:

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

-> 这里在处理过程中出了点问题,但是数据的加载工作正常......所以我会进入调试器检查发生了什么,并查看 loaded_data:

-> here something goes wrong during processing, but the loading of data worked fine... so I'd go into the debugger to check out what happened, and to see the loaded_data:

>>> debug
ipdb> len(loaded_data)
100000

-> 然后我希望能够将此变量保存到交互式命名空间中,以便在调试器外部使用,如下所示:

-> Then I would like to be able to save this variable to the interactive namespace for use outside the debugger, like so:

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

推荐答案

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

You can accomplish this by getting a reference to the outer interpreter's stack frame, and writing to its frame globals.

给定一个带有断点的示例模块,将我们踢到 pdb:

Given a sample module with a breakpoint that kicks us into 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__' 的值:

So here's a quick and dirty function that walks up the stack looking for '__name__' with a value of '__main__' in frame globals:

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
>>>

这篇关于从 python 调试器将变量保存到交互式命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:python __all__ 模块级变量有什么用? 下一篇:为什么 tkinter 模块在通过命令行运行时会引发属性错误,但在通过 IDLE 运行时不会?

相关文章