在我被“eval to be death”打败之前,他就是邪恶的'人群,在这种情况下它是一个必要的邪恶,我无法改变它。 Eval有它的用途,在严格控制的环境中,它非常强大。
然而,我遇到了一个没有明显解决方案的问题,我希望能够超越思维。
>>> mydict = {"a-b": "woohoo"}
>>> mydict["a-b"]
'woohoo'
>>> eval('mydict["a-b"]')
'woohoo'
>>> eval('a-b', mydict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'a' is not defined
不幸的是,最后一个案例是我被迫使用的案例,显然它不起作用。任何想法如何将表达式评估到我的&#39;全局变量&#39;或者&#39;当地人&#39;对象,而不是它解释 - 作为减号运算符?我的&#39;全局变量中的一些键。对象在键名中有破折号,这是我无法控制的数据。
以下评论。
这是更大系统的一部分,用户可以通过api推送JSON数据,我们在内部将数据作为字典处理,然后我们将某些规则应用于数据。管理员从Web界面提供规则作为配置。
最终,我需要允许用户给我一个(可能是复杂的)python one liner并根据字典对其进行评估。那不就是eval
的用途吗?如果有一个更好的方法,我不能指示数据的格式,并且必须允许用户给我一个评估的字符串? Eval很棒,因为它让用户可以做很多很酷的事情,比如使用.get()
和len()
,但显然它有缺点,就像前面提到的无法区分或逃脱{{1} }。
谢谢!
答案 0 :(得分:1)
在评估过程中,您尝试将字符串“a-b”作为符号。传统上,这不起作用,因为“ - ”(连字符)不是 word 。只能在符号名称中使用[A-Za-z0-9_]( word )字符。将连字符更改为下划线可以正常工作:
>>> mydict = {"a_b": "woohoo"}
>>> eval('a_b', mydict)
'woohoo'
>>>
但是,在Python3中,可以在符号中使用许多Unicode字符,有些可能是ASCII连字符的适当替换:
>>> mydict = {"aᐨb": "woohoo"}
>>> eval('aᐨb', mydict)
'woohoo'
>>>
在这里,我使用加拿大音节最后的短水平笔画(虽然显然是滥用此代码的预期用途。)有关此方法的更多信息,请参阅帖子What Unicode symbols are accepted in Python3 variable names?。
我需要允许用户给我一个(可能是复杂的)python 班轮并根据字典对其进行评估。
如果是这种情况,那么a
和b
不应该成为该字典的一部分,这可以解决问题:
>>> mydict = {"a": 34, "b": 13}
>>> eval('a-b', mydict)
21
答案 1 :(得分:1)
不要将mydict
用作评估表达式的全局变量dict,而是让用户以dict的形式访问它:
eval(user_expression, {'data': mydict})
然后用户使用
之类的表达式访问它data['a-b']
而不是尝试使用a-b
作为变量名称,并且需要以某种方式打破Python解析器。如果您可能拥有JSON数组或其他JSON类型而不是JSON对象,那么这一点特别好,因为Python列表不能用作eval
的全局变量环境。
如果你想让语法更好一点,你可以给用户类似Javascript的点属性访问:
class ItemsAsAttributesDict(dict):
def __getattr__(self, name):
return self[name]
# when loading the JSON
dict = json.loads(json_string, object_hook=ItemsAsAttributesDict)
然后就像在Javascript中一样,像data['a']
这样的dict条目可以作为data.a
访问,但像data['a-b']
这样的条目仍然需要括号表示法。
如果您使用mydict
作为全局变量dict,则用户必须使用globals()
来访问不是有效变量名的密钥:
globals()['a-b']
请注意,使用eval
会打开讨厌的攻击媒介。人们会认为这些查询是安全的,他们会评估来自不受信任来源的查询,然后有人会要求提供
__import__('os').system('arbitrary_evil_command')
每个人都会恨你。
此外,使用eval
将您的程序与Python语法联系起来。您可能会将其移植到任何其他语言,特别是因为用户将依赖于列表推导和您可能没有预料到的其他Python功能。您甚至可能很难在Python版本之间进行转换,或者支持不同的Python版本。