考虑以下因素:
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
我甚至不知道怎么问,但我希望函数的全局作用域是我打算运行它的环境,而不必在求值期间编译函数。这可能吗?在
谢谢你的意见
解决方案
^{pr2}$
外部执行上下文是在Python中静态定义的(
f.func_globals
是只读的),所以我想说您想要的是不可能的。原因是因为函数可能成为无效的Python,它的定义上下文在运行时被更改。如果语言允许的话,这将是向库调用中注入恶意代码的一个非常容易的途径。在通过提供可选的全局变量/局部变量对
exec
进行沙箱代码有许多注意事项:可选的全局变量/局部变量仅适用于沙盒中的代码。它们不会影响外部的任何东西,也不会影响到外部的任何东西,如果可以的话,就没有意义了。在
换句话说,所谓的“沙盒”将对象
test
传递给exec运行的代码。要更改test
看到的全局变量,还必须修改对象,而不是按原样传递它。这实际上不可能以任何方式保持它的工作,更不用说对象继续做一些有意义的事情。通过使用其他全局变量,
sandbox
中的任何内容都将看到内置函数。如果要在沙盒中隐藏代码中的部分或所有内置项,则需要在字典中添加一个"__builtins__"
键,该键指向None
(禁用所有内置项)或指向它们的版本。这也限制了对象的某些属性,例如访问函数的func_globals
属性将被禁用。即使移除内置组件,沙盒仍将不安全。您首先信任的仅沙盒代码。
这里有一个简单的概念证明:
在Python中调用函数时,它所看到的全局变量始终是在其中定义的模块的全局变量。(如果这不是真的,函数可能不起作用,它实际上可能需要一些全局值,而您不一定知道这些值是什么。)使用}指定一个全局字典只会影响代码}所看到的全局变量。在
exec
或{exec
'd或{如果您想让一个函数看到其他全局变量,那么您确实必须在传递给
exec
或eval()
的字符串中包含函数定义。当你这样做时,函数的“module”就是它编译时所用的字符串,还有它自己的全局变量(即,你提供的那些)。在您可以通过创建一个新函数来解决这个问题,该函数的代码对象与所调用的相同,但另一个指向全局dict的
func_globals
属性,但这是相当高级的黑客行为,可能不值得。不过,你还是要这样做:相关问题 更多 >
编程相关推荐