说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 的内置函数 eval() 将会执行执行一个以字符串为形式的 Python 表达式。 他非常强大,同时也非常危险,所以我们在使用时要格外小心。
以下是一些简单的使用案例:
eval('1+2')
# 3
a = 2
eval('a*4')
# 8
eval('[*"123"]')
# ['1', '2', '3']
eval('{"a":1}')
# {'a': 1}
eval('{"b": c}', {'c':10})
# {'b': 10}
eval('[i for i in range(2)]')
# [0, 1]
eval() 的语法是:
eval(source, globals=None, locals=None, /)
在全局 globals() 和局部 locals() 命名空间的上下文中计算执行给定的 source 字符串表达式。
source 可以是表示Python表达式的字符串,也可以是 compile() 返回的代码对象。
全局变量 globals 必须是字典,局部变量 locals 可以是任何映射类型,默认为当前全局变量和局部变量。
如果只提供 globals,则 locals 默认也是它。
即:
表达式解析参数 expression 并作为 Python 表达式进行求值(从技术上说是一个条件列表),采用 globals 和 locals 字典作为全局和局部命名空间。 如果存在 globals 字典,并且不包含 __builtins__
键的值,则在解析 expression 之前会插入以该字符串为键以对内置模块 builtins 的字典的引用为值的项。 这样就可以在将 globals 传给 eval()
之前通过向其传入你自己的 __builtins__
字典来控制可供被执行代码可以使用哪些内置模块。 如果 locals 字典被省略则它默认为 globals 字典。 如果两个字典都被省略,则将使用调用 eval()
的环境中的 globals 和 locals 来执行该表达式。 注意,eval() 无法访问闭包环境中的 嵌套作用域 (非局部变量)。
返回值就是表达式的求值结果。 语法错误将作为异常被报告。
该函数还可用于执行任意代码对象(比如由 compile() 创建的对象)。 这时传入的是代码对象,而非一个字符串了。如果代码对象已用参数为 mode 的 'exec'
进行了编译,那么 eval() 的返回值将为 None。
提示: exec() 函数支持语句的动态执行。 globals() 和 locals() 函数分别返回当前的全局和本地字典,可供传给 eval() 或 exec() 使用。
如果给出的源数据是个字符串,那么其前后的空格和制表符将被剔除。
另外可以参阅 ast.literal_eval()
,该函数可以安全执行仅包含文字的表达式字符串。
引发一个 审计事件 exec 附带参数 code_object。
考虑使用 UNIX 系统(Mac OS,Linux等)的情况,然后导入 OS 模块。操作系统模块提供了一种可移植的方式来使用操作系统功能,如读取或写入文件。
如果允许用户使用 eval(input())
输入一个值,则用户可以使用命令:os 发出命令来更改文件,甚至删除所有文件:os.system('rm -rf *')
。警告:千万别试啊!
eval 虽然方便,但是要注意安全性,可以将字符串转成表达式并执行,就可以利用执行系统命令,删除文件等操作。比如用户恶意输入就会获得当前目录文件。
我们可以适当限制命名空间:
from math import *
eval('dir()')
# 所有 math 的命名空间
eval('dir()', {})
# ['__builtins__']
eval('dir()', {'sqrt': sqrt, 'pow': pow})
# ['__builtins__', 'pow', 'sqrt']
# 禁止内置命名空间,内置函数等
eval('dir()', {'__builtins__': None})
# TypeError: 'NoneType' object is not subscriptable
注意:有时,eval() 即使名称有限也不安全。当一个对象及其方法可以访问时,几乎任何事情都可以完成。唯一安全的方法是验证用户输入。
在 Python 中,eval() 函数可以将字符串作为代码执行。但是,使用 eval() 函数时需要非常小心,因为它可以执行任何代码,包括恶意代码。为了确保安全,可以使用 ast.literal_eval() 函数来代替 eval() 函数。ast.literal_eval() 函数只能评估一些基本的 Python 表达式,例如字符串、数字、元组、列表、字典和布尔值,因此它比 eval() 函数更安全。
ast.literal_eval(node_or_string) 计算表达式节点或仅包含Python表达式的字符串。提供的字符串或节点只能由以下Python文本结构组成:字符串、字节、数字、元组、列表、dicts、set、boolean 和 None。
注意:复杂的表达式可能会使 C 堆栈溢出并导致崩溃。
pandas 也提供了全局(pd.eval)和 DataFrame(df.eval) 命名空间下的 eval() 函数和方法,详见 pandas eval()。
更新时间:2023-05-16 17:02:24 标签:python eval 执行