Dan*_*ner 4 python scope eval sandbox
考虑以下:
def test(s):
globals()['a'] = s
sandbox = {'test': test}
py_str = 'test("Setting A")\nglobals()["b"] = "Setting B"'
eval(compile(py_str, '<string>', 'exec'), sandbox)
'a' in sandbox # returns False, !What I dont want!
'b' in sandbox # returns True, What I want
'a' in globals() # returns True, !What I dont want!
'b' in globals() # returns False, What I want
Run Code Online (Sandbox Code Playgroud)
我甚至不确定如何询问,但我希望函数的全局范围成为我打算运行它的环境,而不必在eval期间编译函数.这可能吗?
感谢您的任何意见
解
def test(s):
globals()['a'] = s
sandbox = {}
# create a new version of test() that uses the sandbox for its globals
newtest = type(test)(test.func_code, sandbox, test.func_name, test.func_defaults,
test.func_closure)
# add the sandboxed version of test() to the sandbox
sandbox["test"] = newtest
py_str = 'test("Setting A")\nglobals()["b"] = "Setting B"'
eval(compile(py_str, '<string>', 'exec'), sandbox)
'a' in sandbox # returns True
'b' in sandbox # returns True
'a' in globals() # returns False
'b' in globals() # returns False
Run Code Online (Sandbox Code Playgroud)
当你在Python中调用一个函数时,它看到的全局变量总是它所定义的模块的全局变量.(如果这不是真的,那么函数可能不起作用 - 它实际上可能需要一些全局值,而你不一定知道它们是哪些.)指定全局变量字典,exec或eval()仅影响代码为exec"d"或eval()"d " 的全局变量.
如果你想要一个功能看其他全局变量,那么,你确实必须包括你传递给字符串函数定义exec或eval().当你这样做时,函数的"模块"是它编译的字符串,带有自己的全局变量(即你提供的那些).
您可以通过创建一个新函数来解决这个问题,该函数使用与您正在调用的代码对象相同的代码对象,但是func_globals指向您的全局字典的不同属性,但这是相当高级的hackery,可能不值得.不过,这是你怎么做的:
# create a sandbox globals dict
sandbox = {}
# create a new version of test() that uses the sandbox for its globals
newtest = type(test)(test.func_code, sandbox, test.func_name, test.func_defaults,
test.func_closure)
# add the sandboxed version of test() to the sandbox
sandbox["test"] = newtest
Run Code Online (Sandbox Code Playgroud)