使用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
也是如此。