1

标题似乎很愚蠢,但我不知道如何准确表达,对不起。

我有一个程序需要评估一些用户代码(通过 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)

这将给出结果:

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

在这里使用 'globals()' insde 'err' 当然是错误的。但是我怎样才能在'err'中获得'g'中的值?

4

2 回答 2

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.

于 2012-09-21T09:18:16.080 回答
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
>>> 
于 2012-09-21T10:30:00.037 回答