Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Is there a way to get a local function variable from within a decorator that wraps it?

I'd like to read an object method's local value from a decorator that wraps it. I've got access to the function and func_code from within the decorator but it seems all I can get out of it is the names of the local vars, but not their values.

Is it possible?

like image 217
Harel Avatar asked Feb 08 '12 00:02

Harel


People also ask

Can decorator return value Python?

Python Decorators 101 Return values from decorated functions don't get returned by default unless the decorator allows it. In this lesson, you'll see how to get return values out of decorated functions by making a small change to the decorator.

How do you pass a value dynamically in Python?

Dynamic Function Arguments We simply can make solve_for() accept *args and **kwargs then pass that to func() . Of course, you will need to handle the arguments in the function that will be called.

Can you use a local variable in another function Python?

Variables defined inside functions are called local variables. Their value can only be used within the function where they are declared. You can change the scope of a local variable using the global keyword – which we'll discuss in the next section.

Can we use decorator inside a function in Python?

Nesting means placing or storing inside the other. Therefore, Nested Decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function. It makes decorators useful for reusable building blocks as it accumulates the several effects together.


1 Answers

See https://stackoverflow.com/a/4249347/224295, http://code.activestate.com/recipes/577283-decorator-to-expose-local-variables-of-a-function-/

Working example:

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
like image 194
philofinfinitejest Avatar answered Nov 08 '22 14:11

philofinfinitejest