繁体   English   中英

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

[英]Safe use of eval() or alternatives - python

我总是对用任何语言使用eval感到厌倦,但我想不出一种更好的方法来做两件事。 从我读到的所有内容来看,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())完成。

有一个更好的方法:使用一流的函数。

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许多用法那么糟糕,因为它不评估任意用户输入,而是评估硬编码的字符串。 这完全是不必要的,非常缓慢且丑陋。

对于调试,有专用的调试器。 它们比临时的评估循环更有效。

我建议您将字典值变成某种可调用的对象。 例如,

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

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

name, func = some_dict[1]
func()

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

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

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')]}

为什么不简单地:

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

然后,

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM