在Python中使用Eval创建类变量

1 投票
4 回答
3611 浏览
提问于 2025-04-15 12:58

我写了一个类,可以让我传入一些变量的类型、名字、提示信息和默认值。这个类会创建一个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 个回答

0

对于那些关注安全的人来说,可能有一个可以接受的替代方案。以前有一个叫做rexec的模块,它可以让你“限制”地执行任意的Python代码。不过,这个模块在最近的Python版本中被移除了。http://pypi.python.org/pypi/RestrictedPython是Zope团队提供的另一个实现,它为任意的Python代码创建了一个“受限”的环境。

1

我同意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时可能会构造出各种恶意代码注入。这就要求开发者考虑到代码可能被攻击的所有方式,增加了不必要的风险,而其实有更安全的替代方案。

18

你可以使用 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())

撰写回答