【问题标题】:Get locals from calling namespace in Python从 Python 中调用命名空间获取本地人
【发布时间】:2011-09-30 22:04:22
【问题描述】:

我想从被调用函数中检索 Python 的局部变量。有没有办法做到这一点?我意识到这不适用于大多数编程,但我基本上是在构建一个调试器。例如:

def show_locals():
  # put something in here that shows local_1.

local_1 = 123
show_locals()  # I want this to show local_1.

我在show_locals 的正文中放了什么?如果我必须修改调用语句,我可以做的最小修改是什么?

注意:这必须在 show_locals 与其调用者位于不同模块中时起作用。

【问题讨论】:

    标签: python metaprogramming


    【解决方案1】:

    也许值得指出的是,从调用者的堆栈帧中读取的已接受答案的技术:

    import inspect
    def read_from_caller(varname):
        frame = inspect.currentframe().f_back
        try:
            v = frame.f_locals[varname]
            return v
        finally:
            del frame
    

    也可以写入调用者的命名空间:

    import inspect
    def write_in_caller(varname, v):
        frame = inspect.currentframe().f_back
        try:
            frame.f_locals[varname] = v
        finally:
            del frame
    

    如果你把它放在一个名为“access_caller”的模块中,那么

    import access_caller
    access_caller.write_in_caller('y', x)
    

    是一种精致的写作方式

    y = x
    

    (我写这个作为一个新的答案,因为我没有足够的声誉点来写评论。)

    【讨论】:

    • 嗨@daniel,它似乎至少在python3.8中不起作用。对 f_locals 的 setitem 调用无效
    • 嗨@grégoire-roussel,你能分享一个代码示例吗?对我来说,写“x = 45”,然后“write_in_caller('y', x)”,然后“print(y)”按预期报告 45。我在 linux 中使用 python 3.8.5。
    【解决方案2】:

    如果您正在编写调试器,您将需要大量使用 inspect 模块:

    def show_callers_locals():
        """Print the local variables in the caller's frame."""
        import inspect
        frame = inspect.currentframe()
        try:
            print(frame.f_back.f_locals)
        finally:
            del frame
    

    【讨论】:

    • 超级有帮助。谢谢。
    • 耶!在使用替代解决方案遇到重大性能问题后,我找到了您的解决方案:caller = inspect.stack()[1][0]; myvars = caller.f_locals。你的方式要快得多。
    • 为什么需要删除finally 块中的frame?将框架对象保存在内存中是否有点昂贵?当然,这是一个小问题,但它让我感到困惑。另外,谢谢,这很有帮助!
    • inspect documentation 解释了del frame
    • 啊等等,我明白了。 “超出范围”的字面意思是,拥有局部变量的堆栈帧即将被释放。但是,'frame' 正好指向那个堆栈帧。这就是他们所说的循环。好的,我承认del frame 很有用。 OTOH我不确定该变量是否必要。我认为函数体可以是print(inspect.currentframe().f_back.f_locals)
    【解决方案3】:

    你使用 python 内置,dir() 或 vars():

    变量(对象)

    有关使用 dir() 的示例,请参阅:this post

    使用变量的示例:

    >>> class X:
    ...     a=1
    ...     def __init__(self):
    ...         b=2
    ... 
    >>> 
    >>> vars(X)
    {'a': 1, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x100488848>}
    >>> 
    >>> vars(X())
    {}
    

    一个可能存在问题的事实:新样式类不会返回相同的结果

    >>> class X(object):
    ...     a=1
    ...     def __init__(self):
    ...         b=2
    ... 
    >>> 
    >>> vars(X)
    <dictproxy object at 0x1004a1910>
    >>> vars(X())
    {}
    

    另外:对于一个实例化的类(新旧样式),如果在实例化后添加一个变量,vars 会像这样返回对象的dict

    >>> x = X() 
    >>> x.c = 1
    >>> vars(x)
    {'c': 1}
    >>> 
    

    见:http://docs.python.org/library/functions.html#vars

    【讨论】:

    • 这没有回答问题,OP 想要 func_1 内部的 oppersite,如果你调用 func_2,你可以看到 func_1 的所有本地人。
    猜你喜欢
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 2012-01-08
    • 2022-01-20
    相关资源
    最近更新 更多