一分鍾學個小知識
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))
<class 'str'> <class 'str'>
>>>
>>>
>>>
>>> a1 = eval(data1)
>>> print(a1, type(a1))
['ops-coffee', 'cn'] <class 'list'>
>>>
>>> a2 = eval(data2)
>>> print(a2, type(a2))
{'title': '運維咖啡吧', 'url': 'https://ops-coffee.cn'} <class 'dict'>
>>>
>>>
>>>
>>> b1 = literal_eval(data1)
>>> print(b1, type(b1))
['ops-coffee', 'cn'] <class 'list'>
>>>
>>> b2 = literal_eval(data2)
>>> print(b2, type(b2))
{'title': '運維咖啡吧', 'url': 'https://ops-coffee.cn'} <class 'dict'>
>>>
>>>
除了可以對數據類型進行轉換外,他們還可以對字符串的輸入做處理,例如
>>> 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 "<stdin>", line 1, in <module>
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: <_ast.Call object at 0x7f3b192a24a8>
>>>
所以使用literal_eval
可大大降低系統風險,有着更為安全的表現
相關文章推薦閱讀: