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()
andglobals()
.
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?
source to share
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
source to share