Python中eval和ast.literal_eval的区别

Python中,如果要将字符串型的list,tuple,dict转变成原有的类型呢?这个时候你自然会想到eval. eval函数在Python中做数据类型的转换还是很有用的。它的作用就是把数据还原成它本身或者是能够转化成的数据类型.

string <=> list

In [1]: s = '[1, 2, 3, 4]'

In [2]: l = eval(s)

In [3]: s
Out[3]: '[1, 2, 3, 4]'

In [4]: l
Out[4]: [1, 2, 3, 4]

In [5]: type(s)
Out[5]: str

In [6]: type(l)
Out[6]: list

string <=> tuple

In [9]: s = '(1, 2, 3)'

In [10]: l = eval(s)

In [11]: s
Out[11]: '(1, 2, 3)'

In [12]: l
Out[12]: (1, 2, 3)

In [13]: type(s)
Out[13]: str

In [14]: type(l)
Out[14]: tuple

string <=> dict

In [15]: s = "{'key': 'value'}"

In [16]: d = eval(s)

In [17]: s
Out[17]: "{'key': 'value'}"

In [18]: d
Out[18]: {'key': 'value'}

In [19]: type(s)
Out[19]: str

In [20]: type(d)
Out[20]: dict

eval可以实现从元祖,列表,字典型的字符串到元祖,列表,字典的转换,此外,eval还可以对字符串型的输入直接计算。比如,她会将'1+1'的计算串直接计算出结果。

In [21]: v = eval(raw_input('Please input a string: '))
Please input a string: 1+2

In [22]: v
Out[22]: 3

eval既可以做string与list,tuple,dict之间的类型转换,还可以做计算器使用。更有甚者,可以对它能解析的字符串都做处理,而不顾忌可能带来的后果!所以说eval强大的背后,是巨大的安全隐患!!! 比如说,用户恶意输入下面的字符串

open(r'D://filename.txt', 'r').read()

__import__('os').system('dir')

__import__('os').system('rm -rf /etc/*')

那么eval就会不管三七二十一,显示你电脑目录结构,读取文件,删除文件.....如果是格盘等更严重的操作,它也会照做不误!!! 所以这里就引出了另外一个安全处理方式 ast.literal_eval 。可以先看下stackoverflow及Python官方关于这个解释!

stackoverflow

datamap = eval(raw_input('Provide some data here: ') means that you actually evaluate the code before you deem it to be unsafe or not. It evaluates the code as soon as the function is called. See also the dangers of eval.

ast.literal_eval raises an exception if the input isn't a valid Python datatype, so the code won't be executed if it's not.

Use ast.literal_eval whenever you need eval. If you have Python expressions as an input that you want to evaluate, you shouldn't (have them).

简单点说ast模块就是帮助Python应用来处理抽象的语法解析的。而该模块下的 literal_eval() 函数:则会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算。

比如说上面的计算操作,及危险操作,如果换成了 ast.literal_eval() ,都会拒绝执行。

报值错误,不合法的字符串!

In [24]: ast.literal_eval('1+1')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
 in ()
----> 1 ast.literal_eval('1+1')

/usr/lib/python2.7/ast.pyc in literal_eval(node_or_string)
     78                 return left - right
     79         raise ValueError('malformed string')
---> 80     return _convert(node_or_string)
     81 
     82 

/usr/lib/python2.7/ast.pyc in _convert(node)
     77             else:
     78                 return left - right
---> 79         raise ValueError('malformed string')
     80     return _convert(node_or_string)
     81 

ValueError: malformed string

In [25]: ast.literal_eval("open(r'D://filename.txt', 'r').read()")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
 in ()
----> 1 ast.literal_eval("open(r'D://filename.txt', 'r').read()")

/usr/lib/python2.7/ast.pyc in literal_eval(node_or_string)
     78                 return left - right
     79         raise ValueError('malformed string')
---> 80     return _convert(node_or_string)
     81 
     82 

/usr/lib/python2.7/ast.pyc in _convert(node)
     77             else:
     78                 return left - right
---> 79         raise ValueError('malformed string')
     80     return _convert(node_or_string)
     81 

ValueError: malformed string

而只会执行合法的Python类型,从而大大降低系统的危险性!

所以出于安全考虑,对字符串进行类型转换的时候,最好使用 ast.literal_eval() 函数。

你可能感兴趣的:(Python中eval和ast.literal_eval的区别)