問題
想要將一段列表形式的字符串轉為 list
,但是擔心這個動態的字符串可能是惡意的代碼?使用 eval
將帶來安全隱患。比如:
# 期望是
eval('[1, 2, 3]')
# 實際上是
eval("os.popen('rm -rf *')")
解決方案
使用 ast.literal_eval
可以很好的避免這個問題,該函數可以安全執行僅包含文字的表達式字符串。支持的對象有字符串、字節、數字、元組、列表、字典、集合、 布爾值、None
和 Ellipsis
。這些是可以嵌套的,比如以字典作為元素的列表:
>>> from ast import literal_eval
>>> literal_eval("[{'name': 'john', 'location': 'halo7'}]")
[{'name': 'john', 'location': 'halo7'}]
注意 literal_eval
不可以執行任何復雜的表達式,比如包含運算符或是有索引的表達式都是不支持的,會直接拋出異常。這也保證了它不會執行惡意代碼。
拓展
- 使用
literal_eval
時,足夠復雜或是巨大的字符串可能導致 Python 解釋器的崩潰,因為 Python 的 AST 編譯器是有棧深限制的 literal_eval
解析異常時,可能會拋出ValueError
,TypeError
,SyntaxError
,MemoryError
或RecursionError
,這取決於傳入的字符串