一、eval函数
eval()
官方文档里面给出来的功能解释是:将字符串string
对象转化为有效的表达式参与求值运算返回计算结果。
eval(expression[, globals[, locals]])
参数
- expression -- 表达式。
- globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
- locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。
运用比较多的功能是以下两种:
(资料图片)
1、eval 作为 python 的一个内置函数,用于返回传入的字符串表达式结果。
print(eval("8+10"))# 18x=4;y=9print(eval("x*y"))# 36print(eval("2+6==8"))# True
存在 globals 变量作用域时,取 globals 中变量。
x=2;y=4;z=6g = {"x":10,"y":20}print(eval("x*y",g))# 200
存在 locals 变量作用域时,取 locals 中变量。
x=2;y=4;z=6g = {"x":10,"y":20}l = {"y":30,"z":40}print(eval("x*y",g,l))# 300
2、将字符串转成字典、元祖、列表。
x = "{"a":10,"b":20,"c":30}"print(eval(x))# {"a": 10, "b": 20, "c": 30}y = "[5,10,15]"print(eval(y))# [5, 10, 15]z = "(1,2,3)"print(eval(z))# (1, 2, 3)
虽然 eval 处理字符串的能力很强,但也存在着非常大的安全隐患,因为它具有可以将字符串转成表达式执行的特性,所以它也就可以去执行系统命令。这样很容易被别有用心的人用来执行系统命令,删除关键文件系统,比如用户恶意输入就会获得当前目录文件。
# 获取系统文件eval("__import__("os").system("dir")")
二、ast.literal_eval 函数
ast 模块的 literal_eval 函数是对 python 内置函数 eval 存在安全隐患的一种安全解决方式。它会判断需要计算的内容是不是合法的Python类型,如果是则执行,否则就报错。例如使用 ast.literal_eaval 处理字符串转换。
import astx = "{"a":10,"b":20,"c":30}"print(ast.literal_eval(x))# {"a": 10, "b": 20, "c": 30}y = "[5,10,15]"print(ast.literal_eval(y))# [5, 10, 15]z = "(1,2,3)"print(ast.literal_eval(z))# (1, 2, 3)
ast.literal_eval 不能执行上述 eval 函数的计算操作:
import astast.literal_eval("2+6")"""Traceback (most recent call last): File "d:\program files\python37\Lib\code.py", line 90, in runcode exec(code, self.locals) File "", line 1, in File "d:\program files\python37\Lib\ast.py", line 91, in literal_eval return _convert(node_or_string) File "d:\program files\python37\Lib\ast.py", line 90, in _convert return _convert_signed_num(node) File "d:\program files\python37\Lib\ast.py", line 63, in _convert_signed_num return _convert_num(node) File "d:\program files\python37\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 0x000001AC3D88FB70>"""
当然也不会执行获取、删除文件系统等危险操作:
ast.literal_eval("__import__("os").system("dir")")"""Traceback (most recent call last): File "d:\program files\python37\Lib\code.py", line 90, in runcode exec(code, self.locals) File "", line 2, in File "d:\program files\python37\Lib\ast.py", line 91, in literal_eval return _convert(node_or_string) File "d:\program files\python37\Lib\ast.py", line 90, in _convert return _convert_signed_num(node) File "d:\program files\python37\Lib\ast.py", line 63, in _convert_signed_num return _convert_num(node) File "d:\program files\python37\Lib\ast.py", line 55, in _convert_num raise ValueError("malformed node or string: " + repr(node))ValueError: malformed node or string: <_ast.Call object at 0x000001AC3D89B940>"""
总结:当处理字符串转换时,虽然 eval 函数可以通过变量作用域限制一些危险操作,但无法完全堵住所有非法操作。所以我们使用安全性更高的 ast.literal_eval 替代 eval 函数。