安全使用eval()或替代品 - python

时间:2013-08-09 16:14:59

标签: python python-3.x

我总是厌倦在任何语言中使用eval,但我想不出更好的方法来做两件事。从我读过的所有内容来看,evIl(这很糟糕)。任何想法都表示赞赏。 我有一个带字典的模块,可以根据你从另一个模块调用它的方式来调用函数或设置属性

module Config
some_dict = {1: ["desc 1", "callfunction1()"], 
  2: ["desc2", "setattr(object, "attribute", "the fun things"]} 

module other
try:
  i = int(input())
  eval(Config.some_dict[i][1])
except ValueError:
  print("nope")

我只是想知道是否有更安全的方法来做到这一点 此外,如果我在程序运行时尝试调试:

try:
  eval(input())
except:
  pass

这是可接受的还是pythonic还是有更好的方法?我是python的新手(我主要运行JSL所以一切都是用eval(parse())完成的。

4 个答案:

答案 0 :(得分:5)

有一种更好的方法:使用一流的功能。

def func2():
    setattr(object, "attribute", "the fun things")

some_dict = {
    1: ["desc 1", callfunction1],
    2: ["desc2", func2]
}

i = int(input())
Config.some_dict[i][1]()

如果您对它们感到满意,可以使用lambdapartial减少杂乱。 也就是说,您现有的解决方案并不像eval的许多用途那么糟糕,因为它不会评估任意用户输入,而是评估硬编码字符串。这显然是不必要的,非常缓慢和丑陋。

对于调试,有专门的调试器。它们比ad-hoc eval-loop工作得更好。

答案 1 :(得分:3)

我建议将字典值变成某种类型的callables。例如,

some_dict = {
    1: ["desc 1", callfunction1], 
    2: ["desc2", lambda: setattr(object, "attribute", "the fun things")]
}

然后,当您想要使用字典中的元素时,只需调用它们:

name, func = some_dict[1]
func()

重要的是字典中的每个值都需要具有相同的调用接口(例如,不带参数)。

答案 2 :(得分:0)

您可以将函数存储为字典中的值,因此只需为每个操作创建一个函数,在字典中查找并调用它。

def set_object_attr(obj=object, name='attribute', value='the fun things'):
    setattr(obj, name, value)

some_dict = {1: ["desc 1", callfunction1],
             2: ["desc 2", set_object_attr]}

# then wherever you are using this
some_dict[i][1]()

正如您在此处所见,由于callfunction1已经是一个函数,因此您无需将其包装在另一个调用中。您需要包装setattr()调用,因为您需要能够在没有任何参数的情况下调用该函数。

我在上面写了set_object_attr函数,以明确发生了什么,但在这种情况下,最好使用functools.partial

import functools
some_dict = {1: ["desc 1", callfunction1],
             2: ["desc 2", functools.partial(setattr, object,
                                             'attribute', 'the fun things')]}

答案 3 :(得分:0)

为什么不简单:

some_dict[2]['function'] = setattr
some_dict[2]['options'] = [object, "attribute", "value"]

然后,

if option = 'foo':
   some_dict[2]['function'](*some_dict[2]['options'])