在Python中使用Eval创建类变量
我写了一个类,可以让我传入一些变量的类型、名字、提示信息和默认值。这个类会创建一个wxPython面板,显示在一个框架里,让用户在按下计算按钮之前设置输入值,然后得到结果以图表的形式展示。我通过exec语句把所有变量添加到这个类里。这样,所有变量就都集中在一个类里面,我可以通过名字来引用它们。
light = Variables( frame , [ ['f','wavelength','Wavelength (nm)',632.8] ,\
['f','n','Index of Refraction',1.0],])
在这个类里,我用类似这样的语句来创建和设置变量:
for variable in self.variable_list:
var_type,var_text_ctrl,var_name = variable
if var_type == 'f' :
exec( 'self.' + var_name + ' = ' + var_text_ctrl.GetValue() )
当我需要使用这些变量时,我只需要通过名字来引用它们:
wl = light.wavelength
n = light.n
然后我在StackOverflow上看到,Python中很少需要使用exec。这样做有什么问题吗?有没有更好的方法来创建一个类,把应该放在一起的变量存储在一起,并且可以编辑,同时还包含显示、编辑(以及将所有变量保存到文件或重新读取的代码和wxPython调用)?
Curt
4 个回答
对于那些关注安全的人来说,可能有一个可以接受的替代方案。以前有一个叫做rexec的模块,它可以让你“限制”地执行任意的Python代码。不过,这个模块在最近的Python版本中被移除了。http://pypi.python.org/pypi/RestrictedPython是Zope团队提供的另一个实现,它为任意的Python代码创建了一个“受限”的环境。
我同意mipadi的回答,但我想再补充一点,因为原帖问到使用exec是否有问题。我想对此进行说明。
想象一下,如果你是个坏人。
如果你的对手知道你有这样的代码:
exec( 'self.' + var_name + ' = ' + var_text_ctrl.GetValue() )
那么他们可能会试图注入一些值给var_name和var_text_ctrl,来攻击你的代码。
想象一下,如果一个恶意用户能够让var_name变成这个值:
var_name = """ a = 1 # some bogus assignment to complete "self." statement import os # malicious code starts here os.rmdir('/bin') # do some evil # end it with another var_name # ("a" alone, on the next line) a """
突然间,这个恶意对手就能让你执行一段代码,删除你的/bin目录(或者他们想做的任何坏事)。现在你的exec语句大致上变成了:
exec ("self.a=1 \n import os \n os.rmdir('/bin') \n\n " "a" + ' = ' + var_text_ctrl.GetValue() )
这可不好!!!
正如你所想的,使用exec时可能会构造出各种恶意代码注入。这就要求开发者考虑到代码可能被攻击的所有方式,增加了不必要的风险,而其实有更安全的替代方案。
你可以使用 setattr
这个函数,它需要三个参数:对象、属性的名字和它的值。比如说,
setattr(self, 'wavelength', wavelength_val)
这和下面的内容是一样的:
self.wavelength = wavelength_val
所以你可以这样做:
for variable in self.variable_list:
var_type,var_text_ctrl,var_name = variable
if var_type == 'f' :
setattr(self, var_name, var_text_ctrl.GetValue())