# Python `eval()`函数
> 原文: [https://thepythonguru.com/python-builtin-functions/eval/](https://thepythonguru.com/python-builtin-functions/eval/)
* * *
于 2020 年 1 月 7 日更新
* * *
`eval()`允许我们执行任意字符串作为 Python 代码。 它接受源字符串并返回一个对象。
其语法如下:
**语法**:
```py
eval(expr, globals=None, locals=None)
```
| 参数 | 描述 |
| --- | --- |
| `expr`(必填) | `expr`可以是任何有效的 Python 表达式 |
| `globals`(可选) | 执行源时要使用的全局名称空间。 它必须是字典。 如果未提供,则将使用当前的全局名称空间。 |
| `locals`(可选) | 执行源时要使用的本地名称空间。 它可以是任何映射。 如果省略,则默认为`globals`字典。 |
如果同时省略`globals`和`locals`,则使用当前的全局和局部名称空间。
这是一个演示`eval()`如何工作的示例:
```py
>>>
>>> eval("5 == 5")
True
>>>
>>>
>>> eval("4 < 10")
True
>>>
>>>
>>> eval("8 + 4 - 2 * 3")
6
>>>
>>>
>>> eval("'py ' * 5")
'py py py py py '
>>>
>>>
>>> eval("10 ** 2")
100
>>>
>>>
>>> eval("'hello' + 'py'")
'hellopy'
>>>
```
试试看:
```py
print(eval("5 == 5"))
print(eval("4 < 10"))
print(eval("8 + 4 - 2 * 3"))
print(eval("'py ' * 5"))
print(eval("10 ** 2"))
print(eval("'hello' + 'py'"))
```
`eval()`不仅限于简单表达。 我们可以执行函数,调用方法,引用变量等。
```py
>>>
>>> eval("abs(-11)")
11
>>>
>>>
>>> eval('"hello".upper()')
'HELLO'
>>>
>>>
>>> import os
>>>
>>>
>>> eval('os.getcwd()') # get current working directory
'/home/thepythonguru'
>>>
>>>
>>> x = 2
>>>
>>> eval("x+4") # x is referenced inside the expression
6
>>>
```
试一试:
```py
print(eval("abs(-11)"))
print(eval('"hello".upper()'))
import os
# get current working directory
print(eval('os.getcwd()'))
x = 2
print(eval("x+4")) # x is referenced inside the expression
```
请注意,`eval()`仅适用于表达式。 尝试传递语句会导致`SyntaxError`。
```py
>>>
>>> eval('a=1') # assignment statement
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
a=1
^
SyntaxError: invalid syntax
>>>
>>>
>>> eval('import re') # import statement
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
import re
^
SyntaxError: invalid syntax
>>>
```
## 邪恶的`eval()`
* * *
您永远不要直接将不受信任的源传递给`eval()`。 由于恶意用户很容易对您的系统造成破坏。 例如,以下代码可以用于从系统中删除所有文件。
```py
>>>
eval('os.system("RM -RF /")') # command is deliberately capitalized
>>>
```
如果`os`模块在您当前的全局范围内不可用,则以上代码将失败。 但是我们可以通过使用`__import__()`内置函数轻松地避免这种情况。
```py
>>>
>>> eval("__import__('os').system('RM -RF /')") # command is deliberately capitalized
>>>
```
那么有什么方法可以使`eval()`安全吗?
## 指定命名空间
* * *
`eval()`可选地接受两个映射,作为要执行的表达式的全局和局部名称空间。 如果未提供映射,则将使用全局和局部名称空间的当前值。
这里有些例子:
**示例 1**:
```py
>>>
>>> globals = {
... 'a': 10,
... 'fruits': ['mangoes', 'peaches', 'bananas'],
... }
>>>
>>>
>>> locals = {}
>>>
>>>
>>> eval("str(a) + ' ' + fruits[0]", globals, locals)
'10 mangoes'
>>>
```
**示例 2**:
```py
>>>
>>> eval('abs(-100)', {}, {})
100
>>>
```
即使我们已经将空字典作为全局和本地名称空间传递了,`eval()`仍可以访问内置函数(即`__builtins__`)。
```py
>>>
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError',
...
...
'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted'
, 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
>>>
```
要从全局名称空间中删除内置函数,请传递一个字典,该字典包含一个值为`None`的键`__builtins__`。
**示例 3**:
```py
>>>
>>> eval('abs(-100)', {'__builtins__':None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable
>>>
```
即使删除对内置函数的访问权限后,`eval()`仍然不安全。 考虑以下清单。
```py
>>>
>>> eval("5**98765432111123", {'__builtins__':None}, {})
>>>
```
这个看似简单的外观表达式足以使您的 CPU 崩溃。
关键要点是仅将`eval()`与受信任的源一起使用。
* * *
* * *
- 初级 Python
- python 入门
- 安装 Python3
- 运行 python 程序
- 数据类型和变量
- Python 数字
- Python 字符串
- Python 列表
- Python 字典
- Python 元组
- 数据类型转换
- Python 控制语句
- Python 函数
- Python 循环
- Python 数学函数
- Python 生成随机数
- Python 文件处理
- Python 对象和类
- Python 运算符重载
- Python 继承与多态
- Python 异常处理
- Python 模块
- 高级 Python
- Python *args和**kwargs
- Python 生成器
- Python 正则表达式
- 使用 PIP 在 python 中安装包
- Python virtualenv指南
- Python 递归函数
- __name__ == "__main__"是什么?
- Python Lambda 函数
- Python 字符串格式化
- Python 内置函数和方法
- Python abs()函数
- Python bin()函数
- Python id()函数
- Python map()函数
- Python zip()函数
- Python filter()函数
- Python reduce()函数
- Python sorted()函数
- Python enumerate()函数
- Python reversed()函数
- Python range()函数
- Python sum()函数
- Python max()函数
- Python min()函数
- Python eval()函数
- Python len()函数
- Python ord()函数
- Python chr()函数
- Python any()函数
- Python all()函数
- Python globals()函数
- Python locals()函数
- 数据库访问
- 安装 Python MySQLdb
- 连接到数据库
- MySQLdb 获取结果
- 插入行
- 处理错误
- 使用fetchone()和fetchmany()获取记录
- 常见做法
- Python:如何读取和写入文件
- Python:如何读取和写入 CSV 文件
- 用 Python 读写 JSON
- 用 Python 转储对象