Python 函数 eval 与 ast.literal_eval 的区别
2013 年 12 月 31 日
一分钟学个小知识
eval
与 ast.literal_eval
都可以将字符串还原成它能够转化成的数据类型,例如
>>> from ast import literal_eval >>> >>> data1 = "['ops-coffee','cn']" >>> data2 = "{'title':'运维咖啡吧','url':'https://ops-coffee.cn'}" >>> >>> print(type(data1),type(data2)) >>> >>> >>> >>> a1 = eval(data1) >>> print(a1, type(a1)) ['ops-coffee', 'cn'] >>> >>> a2 = eval(data2) >>> print(a2, type(a2)) {'title': '运维咖啡吧', 'url': 'https://ops-coffee.cn'} >>> >>> >>> >>> b1 = literal_eval(data1) >>> print(b1, type(b1)) ['ops-coffee', 'cn'] >>> >>> b2 = literal_eval(data2) >>> print(b2, type(b2)) {'title': '运维咖啡吧', 'url': 'https://ops-coffee.cn'} >>> >>>
除了可以对数据类型进行转换外,他们还可以对字符串的输入做处理,例如
>>> eval('1+1') 2 >>> >>> >>> literal_eval('1+1') 2
那么他们有何区别呢?
eval
会对所有他能解析的字符串都做处理,而 literal_eval
则会判断需要处理的内容处理后是不是合法的python类型,如果是则处理,否则不处理
例如在以下例子中
>>> std = input('please input: ') please input: __import__('os').system('ls /') >>> print('out: ',eval(std)) bin boot dev etc lib lost+found opt proc root run sbin selinux srv static sys tmp usr var out: 0 >>>
eval
处理了输入的指令,这是非常危险的,在这里仅仅是用了 ls
查看做测试,如果是 rm
之类的指令后果就会很严重,而对于 literal_eval
则会去判断要解析的内容是否安全,不安全就报错
>>> >>> print('out: ',literal_eval(std)) Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python3.6/ast.py", line 85, in literal_eval return _convert(node_or_string) File "/usr/local/lib/python3.6/ast.py", line 84, in _convert raise ValueError('malformed node or string: ' + repr(node)) ValueError: malformed node or string: >>>
所以使用 literal_eval
可大大降低系统风险,有着更为安全的表现
