eval()
eval函数在Python中的作用就是做数据类型的转换,把数据还原成它本身或是能够转换成的数据类型,官方解释为:将字符串str当成有效的表达式来求值并返回计算结果
使用eval可以实现从元祖,列表,字典型的字符串到元祖,列表,字典的转换,
>>> a='[1,2,3]' >>> b=eval(a) >>> b [1, 2, 3] >>> type(a) <class 'str'> >>> type(b) <class 'list'> >>> c="{1:'a',2:'b'}" >>> d=eval(c) >>> d {1: 'a', 2: 'b'} >>> print(type(c),type(d)) <class 'str'> <class 'dict'>
eval不仅可以转换数据类型,还可以直接计算出结果,例如:
>>> e='1+1' >>> f=eval(e) >>> f 2
所以eval强大的背后,也存在着巨大的隐患,例如,用户恶意输入一下字符串:
>>> eval("os.system('whoami')") desktop-odh0osg\xx 0 >>>
open(r'D://filename.txt', 'r').read() __import__('os').system('dir') __import__('os').system('rm -rf /etc/*')
那么eval就会执行这些命令,显示你电脑目录结构,读取文件,删除文件…如果是格盘等更严重的操作,也会执行,在实际开发中,就会出现很严重的事故!
ast.literal_eval()
这里就可以使用ast.literal_eval,安全的处理问题,
简单点说ast模块就是帮助Python应用来处理抽象的语法解析的。而该模块下的literal_eval()
函数:则会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算。
比如说上面的计算操作,及危险操作,如果换成了ast.literal_eval()
,都会拒绝执行。报值错误,不合法的字符串!
官方给出的解释:
ast.``literal_eval
(node_or_string)
安全计算表达式节点或包含Python字面值或容器显示的字符串。提供的字符串或节点只能由以下Python字面值结构组成:字符串,字节,数字,元组,列表,项,集,布尔值和None
。
这可以用于安全地评估包含来自不可信来源的Python值的字符串,而不需要解析值自己。它不能够评估任意复杂的表达式,例如涉及运算符或索引。
>>> import ast
>>> ast.literal_eval('1+1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\users\xx\anaconda3\Lib\ast.py", line 91, in literal_eval
return _convert(node_or_string)
File "c:\users\xx\anaconda3\Lib\ast.py", line 90, in _convert
return _convert_signed_num(node)
File "c:\users\xx\anaconda3\Lib\ast.py", line 63, in _convert_signed_num
return _convert_num(node)
File "c:\users\xx\anaconda3\Lib\ast.py", line 55, in _convert_num
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.BinOp object at 0x0000029751A13390>
>>>
>>> ast.literal_eval('[1,2,3]') [1, 2, 3] >>> ast.literal_eval('(1,2.3,4)') (1, 2.3, 4) >>>
在实际开发中,为了避免不必要的麻烦,可以使用ast.literal_eval(),来获取原来的数据类型,