Reputation: 780
The title seems stupid but i don't know how to express it precisely, sorry.
I have a program that need to eval some user code (through RestrictedPython for security) and I want to put a function into the eval's globals so that it can print out some debug information to me when eval, for example (simplify):
class UserException(Exception):
pass
def err(msg):
# ? how to get the globals variable in eval ?
A = globals().get('A', 'A not found')
return UserException("%s and A's value is %r" % (msg, A))
g = {
'err': err,
'A': None,
'__builtins__': {},
}
print eval('A or err("A not true")', g)
this will give the resut:
A not true and A's value is 'A not found'
Using 'globals()' here insde 'err' is of course wrong. But how can i get the value in 'g' inside 'err'?
Upvotes: 1
Views: 398
Reputation: 95632
Any reference to globals()
from inside a function will always give you the globals that were in scope when the function was defined. What you are seeing here is no different than when you import a function from one module into another: the imported function still refers to the globals of the module where it was defined.
The simplest way to get the function to use g
as its globals()
would be to exec the definition using g
as the globals. If you do change the globals for the function then don't foget you also need to include any other globals that the function uses; in this case UserException
.
Alternatively you could make err()
inspect the stack frame of its caller and use the caller's globals. That's messy, but if it's for debug information may be acceptable to you.
>>> def err(msg):
# ? how to get the globals variable in eval ?
A = sys._getframe(1).f_globals.get('A', 'A not found')
return UserException("%s and A's value is %r" % (msg, A))
>>> import sys
>>> g = {
'err': err,
'A': None,
'__builtins__': {},
}
>>> print eval('A or err("A not true")', g, g)
A not true and A's value is None
>>>
Upvotes: 1
Reputation: 375415
You could pass it g
as a default argument:
def err(msg, g=g):
A = g['A']
return UserException("%s and A's value is %r" % (msg, A))
will give the result: A not true and A's value is None
.
Upvotes: 1