如何为Python函数设置环境变量?
在Lua中,有一个内置的函数叫做 setfenv()
,它可以让你提供一个变量表,作为一个函数的环境。下面是一个使用这个函数的例子:
foo = 1
function f()
print(blech) --Note that no variable named blech has been defined.
end
variableTable = {blech = foo}
setfenv(f, variableTable)
f() -- This will work and print 1, because blech has been defined as foo's value in the variableTable
我这样做的原因是,这样可以为用户搭建一个平台,让他们能够用Lua编写易于理解的脚本(他们可以写不带参数的函数,并且可以放心地相信变量会存在)。这也提供了一种优雅的方法,来排除我不希望他们使用的模块和函数,以确保安全性(例如,如果你定义的变量表中没有os模块,那么更有经验的用户就无法恶意使用它)。
我希望在Python中也能实现同样的功能。Python中有没有类似的做法呢?
5 个回答
2
你为什么想这么做呢?难道你的代码变得太容易理解了吗?
直接把一个字典或者结构体(struct)传给函数就行了,里面放你的“环境”信息。
编辑:看看你的动机。第一部分我不太明白(在Python里写Lua脚本?这是什么意思?),第二部分明显是错的。这并不能限制环境。首先,你还是可以import os
。
限制执行是个比较复杂的话题。我知道的一些内容有:
- Python的限制模块 - http://docs.python.org/library/restricted.html。这个已经不再推荐使用了。
- 一个过时的维基页面 - http://wiki.python.org/moin/SandboxedPython。里面没有什么特别有用的内容。
- PyPy。这可能是个不错的选择。PyPy沙箱文档:http://codespeak.net/pypy/dist/pypy/doc/sandbox.html
3
我不太明白你为什么想这么做,不过这里有一种比较“hacky”的方法:
def foo():
print bar
foo.func_globals['bar'] = 1
foo()
注意:这不是我推荐的做法。
5
这里有个叫做 exec
的东西:
def foo():
print bar
exec foo.func_code in {"bar": "baz"}
用这个方法其实不是个好主意(我甚至觉得这特别糟糕)。因为它让 foo
的实现变得难以理解,因为你得知道它是怎么被调用的。更好的做法是把参数直接传给函数。
而且,这个方法 并没有 提供任何安全保障。简单来说,Python 本身并不支持限制执行的功能。没有任何东西能阻止用户自己提供这个 foo
的定义:
def foo():
import os
os.system("rm -rf /")
就算你没有在映射中提供 os
,也不代表他们不能自己去获取它。如果你真的需要限制执行的功能,可能更适合使用 Lua,或者至少可以看看 PyPy 的沙盒模式。