Is it possible to get locals () and globals () from the top of the stack frame?

If I say something in Python:

eval("a + b")

      

This will evaluate the expression using the current scope (both local and global).

What I am developing requires the expression to be evaluated "later". This word implies that I want to keep the current volume (i.e. locals()

and globals()

). But I want to pass values ​​like this ... transparently or pop them from the top stack. Consider this implementation (in fact, it exists):

def __eval(self, expr):
    if isinstance(expr, (list, tuple, set, frozenset, dict, Expression)):
        return Expression.eval(expr, self)
    elif callable(expr):
        try:
            return expr(self)
        except (AttributeError, IndexError, KeyError, TypeError):
            return UNDEFINED
    else:
        try:
            return eval(expr, {}, {'self': self})
        except (AttributeError, IndexError, KeyError, TypeError):
            return UNDEFINED

      

This implementation is explained as follows:

  • If I use an expression object (I actually created such an object), then I evaluate that expression using the current object (after all, this function is a method). This part needs no help, it is fully developed.
  • If I use a callable, I execute the callable (like a lambda expression).
  • If I use a string, it is a python expression and I want such an evaluation to be done using the call time locals()

    and globals()

    .

I know I can explicitly call:

o._O__eval("self.a + self.b", globals(), locals())
#THIS WOULD REQUIRE to alter the method to allow two additional dict parameters
#NO, I will not call this function directly, but lets follow the example

      

But I would like to get such globals()

and locals

if the user did not explicitly pass it in and use such values ​​in eval

.

Question : Is it possible to get locals()

and globals()

from the upper frame stack?

+3


source to share


1 answer


You should really only consider going through globals()

and locals()

:

def __eval(self, expr, eval_globals=None, eval_locals=None):
    if eval_globals is None:
        eval_globals = globals()
    if eval_locals is None:
        eval_locals = eval_globals()

      



If that's not an option for you, you can access the parent frame using a function sys._getframe()

, and the local and global attributes in that frame:

def __eval(self, expr, eval_globals=None, eval_locals=None):
    call_frame = sys._getframe(1)
    eval_globals, eval_locals = call_frame.f_globals, call_frame.f_locals

      

+3


source







All Articles