【问题标题】:Examining local variables up the stack in python在python中检查堆栈中的局部变量
【发布时间】:2020-02-24 04:09:50
【问题描述】:

我写了一个小函数,它在堆栈中查找一层并查看其中是否有变量。但是如何将这个函数变成一个在堆栈中一直查找直到找到一个局部变量的函数?

import inspect
def variable_lookup(variable):
    parent_locals = inspect.currentframe().f_back.f_locals
    if variable in parent_locals.keys():
        return parent_locals[variable]

我想要的是循环,直到它遍历所有堆栈,试图找到变量。我如何使用检查来做到这一点?有没有更简单的方法?

我从这个开始,但是 f_back 没有返回一个框架对象,所以我不知道从这里去哪里:

import inspect
def variable_lookup(variable):
previous_frame = inspect.currentframe().f_back
while True:
    print(variable in previous_frame.f_locals.keys())
    previous_frame = inspect.getframeinfo(previous_frame)

因此代码在AttributeError: 'Traceback' object has no attribute 'f_locals' 下失败

【问题讨论】:

  • parent_locals.keys 不是字典。那是方法参考。您也不需要调用keys(),只需使用if variable in parent_locals:
  • 真的很好奇你为什么需要这个。似乎正在颠覆一些设计。可能有更好的方法来做到这一点。
  • @PeterWood:不过,它在调试奇怪问题时会很有帮助。
  • @PeterWood 我只是在处理一个边缘案例,在这种情况下,一个特定的函数可以在不需要将该值传递给它的情况下查看某物的值,这将是非常好的。
  • 如果函数是成员函数,它所在的对象可以携带状态而不是传递给函数。

标签: python scope callstack


【解决方案1】:

有一个更高级别的函数可用:inspect.stack()。这将为您提供FrameInfo() 对象的列表,这些对象具有frame 引用:

for frameinfo in inspect.stack(0):
    if variable in frameinfo.frame.f_locals:
        return frameinfo.frame.f_locals[variable]

我将源代码行数(context 参数)设置为零,加载源代码行只是为了检查局部变量。

stack()函数基本实现为:

return inspect.getouterframes(inspect.currentframe(), context)

getouterframes() 只是跟随frame.f_back 引用,直到找到None。所以你也可以使用while 循环来实现它:

frame = inspect.currentframe()
while frame:
    if variable in frame.f_locals:
        return frame.f_locals[variable]
    frame = frame.f_back

这当然更轻,因为这避免了为堆栈中的所有帧创建FrameInfo() 实例,避免了对所有帧的文件名的自省,并且如果尽早找到变量,则不需要访问所有链接的帧。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多