Python:有没有办法从包装它的装饰器中获取本地函数变量?

Har*_*rel 15 python decorator

我想从包装它的装饰器中读取对象方法的本地值.我可以从装饰器中访问函数和func_code,但似乎我可以得到的只是本地变量的名称,而不是它们的值.

可能吗?

phi*_*est 13

/sf/answers/297454321/,http://code.activestate.com/recipes/577283-decorator-to-expose-local-variables-of-a-function-/

工作范例:

import sys

class persistent_locals(object):
    def __init__(self, func):
        self._locals = {}
        self.func = func

    def __call__(self, *args, **kwargs):
        def tracer(frame, event, arg):
            if event=='return':
                self._locals = frame.f_locals.copy()

        # tracer is activated on next call, return or exception
        sys.setprofile(tracer)
        try:
            # trace the function call
            res = self.func(*args, **kwargs)
        finally:
            # disable tracer and replace with old one
            sys.setprofile(None)
        return res

    def clear_locals(self):
        self._locals = {}

    @property
    def locals(self):
        return self._locals

@persistent_locals
def func():
    local1 = 1
    local2 = 2

func()
print func.locals
Run Code Online (Sandbox Code Playgroud)

  • 好戏.我正在制作一个调试器,它必须偷偷地从装饰函数中抓取内部构件,因此它是合法有用的.需要注意的一点是,tracer()不仅在返回装饰函数时被调用,而且还在从该函数内调用的所有函数的返回时调用.由于修饰函数总是具有最后一个返回(因此将_locals设置为最后),因此在这种情况下无关紧要. (2认同)

Ben*_*Ben 6

你所要求的并没有多大意义.

函数的局部变量始终没有值.考虑这个功能:

def foo(x):
    y = x + 27
    return y
Run Code Online (Sandbox Code Playgroud)

foo本地变量的值是y多少?你无法回答,这个问题在你打电话之前甚至都没有意义foo(即便如此,直到y = x + 27执行这条线为止).

即便如此,此时不仅y可能没有价值,也可能有任何数量的"飞行中"执行foo.可能有线程正在执行foo,或者foo可能是递归的(可能是间接的),因此即使在单个调用堆栈中也有多个正在进行的调用.或者foo可能是一个生成器,因此foo即使没有递归也可能有许多飞行中的执行(即它们不是从一些最外层的foo范围都可以到达).那么y你会得到什么价值?

除非你在范围内谈论,否则yin 的价值foo并不是一个定义明确的概念foo.


鉴于Python的灵活性,我非常确定可以进行堆栈帧内省并找到foo当前存在的堆栈帧并在当时拉出其局部变量的值.这对装饰器来说非常困难(如果不是不可能),因为(除非foo是生成器)装饰器只能添加包装代码"around" foo,这意味着装饰器控制的代码在运行之前和之后foo运行,所以你只有当foo堆栈帧不存在时才能获得控制权.

我不会详细说明如何做到这一点,因为我不知道该怎么做.听起来这几乎肯定是一个坏主意,除非你正在编写调试器.