将函数变量转储到python/ipython中的工作区



当使用python/ipython repl进行开发和调试时,在某个时刻,我想将函数中的所有局部变量转储到工作区,看看发生了什么

def func():
    a = "blablabla"
    b = 1234
    c = some_calculation_of_a_and_b(a,b)
    dump_to_workspace(a,b,c)   # is this possible?,  or even more preferable:
    dump_all_local_variables_to_workspace()   # is this possible?

我希望能够在python/ipython:中运行这个

>>> func()
>>> print a
"blablabla"
>>> print b
1234
>>> print c
some_calculated_value

我知道两种选择:(1)返回函数中的变量[不好,因为我不想弄乱返回值],和(2)将数据保存到磁盘上的文件中[不方便,因为它涉及可能有大量数据的磁盘I/O]。但在大多数情况下,这些都不那么方便。有没有办法直接实现倾销?

提前感谢!

这是一个巨大的破解,但我经常在我的jupyter笔记本电脑中使用它,将一些本地状态转储到全局工作区以供进一步检查。只需将这两行添加到函数的末尾,就可以直接从笔记本访问所有本地变量:

import inspect
inspect.getmodule(next(frm[0] for frm in reversed(inspect.stack())
                       if frm[0].f_locals.get('__name__', None) == '__main__')).__dict__.update(locals())

它所做的是以相反的顺序遍历堆栈(使用inspect模块),以找到名为'__main__'的最顶部模块。这是表示笔记本的模块(即当前内核)。然后,它使用__dict__和函数的局部(使用__locals__)更新模块的全局变量定义

以下是笔记本中的演示:https://colab.research.google.com/drive/1lQgtmqigCUmzVhkX7H7azDWvT3CfxBtt

#%%
def some_calculation_of_a_and_b(a, b):
    return 'some_calculated_value'
def func():
    a = "blablabla"
    b = 1234
    c = some_calculation_of_a_and_b(a,b)
    #dump_all_local_variables_to_workspace():
    import inspect
    inspect.getmodule(next(frm[0] for frm in reversed(inspect.stack())
                      if frm[0].f_locals.get('__name__', None) == '__main__')).__dict__.update(locals())
#%%
func()
print(a)
print(b)
print(c)
# this will print:
# blablabla
# 1234
# some_calculated_value

要实现问题中直接要求的内容,函数可以return locals(),然后您可以在交互式环境中更新locals()

def func():
    # define a,b,c
    return locals() # or, more restrictively, return {'a':a, 'b':b, 'c':c}
>>> locals().update(func())

为了扩展我上面的评论,这里有一个关于pdb:的快速介绍

import pdb
def func():
    a = "blablabla"
    b = 1234
    c = some_calculation_of_a_and_b(a,b)
    pdb.set_trace()

要运行:

python program.py

然后解释器将停在pdb.set_trace()行,允许您观察abc的值。

停止时,您可以通过键入:打印本地变量的值

p a
p b

等等。在pdb提示符下键入?可以获得pdb中命令的完整列表。这是图书馆文档的链接。

您有一个函数:

print locals()

和全局变量的CCD_ 12

您可以在ipython中使用whos。python环境下的vars()

我在Jupyter上下文中遇到了同样的问题。特别是当你想使用Jupyter本身来帮助调试或绘制一些局部时,或者如果你想交互式地编写在深度嵌套函数中运行的代码,并且你想通过根据真实数据进行编写来构建它。

以下是一个github函数的要点,大致基于stav上面的回答(笔记本的顶层与ipython不同)。这是用python 3.8编写的,以备不时之需。

def copy_locals()
'''
    copies all local variables from this context into the jupyter top level, eg, for easier 
    debugging of data and for prototyping new code that is eventually meant to run within this context.
'''
  stack = inspect.stack()
  caller = stack[1]
  local_dict = {k:v  for k,v in caller.frame.f_locals.items() if not k.startswith('_')}
  notebook_caller = None
  for st in stack:
    if st.function == '<module>':        
        notebook_caller = st
        break
        
  if notebook_caller is None:
    print('is this being called from within a jupyter notebook?')
    return
  print('copying variables to <module> globals...', list(local_dict.keys()))
  notebook_caller.frame.f_globals.update(local_dict)

然后,如果你用breakpoint()设置了一个断点,或者你崩溃了,并且你在pdb中,你可以在pdb:中调用copy_cals

%debug
  copy_locals()

并在笔记本上继续工作。

最新更新