最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

环球简讯:eval和ast.literal_eval区别

来源:博客园

一、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 函数。

关键词: 执行系统 安全隐患 命名空间