使用python的eval()与ast.literal_eval()?

我有一个代码的地方eval()作为一个可能的解决scheme。 现在我从来没有必须使用eval() ,但是我已经遇到了很多关于潜在危险的信息。 这就是说,我对使用它非常谨慎。

我的情况是,我有一个用户input:

 datamap = raw_input('Provide some data here: ') 

数据datamap需要成为一个字典。 我四处search,发现eval()可以解决这个问题。 我想我可能能够在尝试使用数据之前检查input的types,这将是一个可行的安全措施。

 datamap = eval(raw_input('Provide some data here: ') if not isinstance(datamap, dict): return 

我仔细阅读了文档,而且我还不清楚这是否安全。 eval是否在数据库variables被调用后立即评估数据?

ast模块的.literal_eval()是唯一安全的选项吗?

datamap = eval(raw_input('Provide some data here: '))意味着你实际上评估代码之前,你认为是不安全的。 只要函数被调用,它就会对代码进行评估。 另见eval的危险 。

如果input不是有效的Python数据types,则ast.literal_eval会引发exception,所以如果不是,则不会执行代码。

每当需要eval时使用ast.literal_eval 。 你通常不应该评估文字Python语句。

ast.literal_eval()只考虑Python语法的一小部分是有效的:

提供的string或节点可能只包含以下Python文字结构:string,数字,元组,列表,字典,布尔值和无。

__import__('os').system('rm -rf /a-path-you-really-care-about') ast.literal_eval()ast.literal_eval()会引发一个错误,但是eval()会快乐地擦除你的驱动器。

由于它看起来像只让用户input一个普通的字典,使用ast.literal_eval() 。 它可以安全地做你想要的,而不是更多。

Python在评估中非常渴望 ,所以eval(raw_input(...))会在用户input到达eval立即评估用户的input,而不pipe之后对数据做什么。 因此, 这是不安全的 ,特别是当你eval用户input。

使用ast.literal_eval


举个例子,在提示符下input这个对你来说是非常非常糟糕的:

 __import__('os').system('rm -rf /a-path-you-really-care-about') 

eval:这是非常强大的,但是如果你接受string来评估不可信的input,这也是非常危险的。 假设被评估的string是“os.system('rm -rf /')”? 这将真正开始删除您的计算机上的所有文件。

ast.literal_eval:安全地评估包含Python文字或容器显示的expression式节点或string。 提供的string或节点可能只包含以下Python文字结构:string,字节,数字,元组,列表,字典,集合,布尔值,无,字节和集合。

句法:

 eval(expression, globals=None, locals=None) ast.literal_eval(node_or_string) 

例:

 ast.literal_eval("1+1") # output : 2 ast.literal_eval("{'a': 2, 'b': 3, 3:'xyz'}") # output : {'a': 2, 'b': 3, 3:'xyz'} # type dictionary ast.literal_eval("",{}) # output : Syntax Error required only one parameter ast.literal_eval("__import__('os').system('rm -rf /')") # output : error eval("__import__('os').system('rm -rf /')") # output : start deleting all the files on your computer. # restricting using global and local variables eval("__import__('os').system('rm -rf /')",{'__builtins__':{}},{}) # output : Error due to blocked imports by passing '__builtins__':{} in global # But still eval is not safe. we can access and break the code as given below s = """ (lambda fc=( lambda n: [ c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == n ][0] ): fc("function")( fc("code")( 0,0,0,0,"KABOOM",(),(),(),"","",0,"" ),{} )() )() """ eval(s, {'__builtins__':{}}) 

如果你所需要的只是用户提供的字典,可能更好的解决scheme是json.loads 。 主要的限制是json dicts需要string键。 另外,您只能提供文字数据,但literal_eval也是如此。