2012-09-21 112 views
1

标题似乎很愚蠢,但我不知道如何精确地表达它,抱歉。Python:如何访问eval的全局变量()里面的eval

我有一个程序,需要评估一些用户代码(通过RestrictedPython的安全性),我想把一个函数放入eval的全局变量中,以便在eval时可以打印出一些调试信息给我):

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) 

这会给resut:

A not true and A's value is 'A not found' 

使用 '全局()' 在这里insde '犯错' 当然是错误的。但是我怎么能在'err'里面得到'g'的值呢?

回答

1

从函数内部对globals()的任何引用将始终为您提供定义该函数时在范围内的全局变量。这里所看到的与从一个模块导入另一个模块时没有什么不同:导入的函数仍然引用定义模块的全局变量。

使用g作为其globals()函数的最简单方法是使用g作为全局变量来执行定义。如果你确实改变了函数的全局变量,那么不要忘了你还需要包含函数使用的其他全局变量;在这种情况下为UserException

或者,你可以让err()检查其调用者的堆栈帧并使用调用者的全局变量。这很麻烦,但如果它是用于调试的信息,那么您可能会接受。

>>> 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 
>>> 
+0

是的,这就是我要找的。我使用检查模块来达到同样的效果。 – jayven

1

你可以通过它g作为默认参数:

def err(msg, g=g): 
    A = g['A'] 
    return UserException("%s and A's value is %r" % (msg, A)) 

会给结果:A not true and A's value is None