企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 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()`与受信任的源一起使用。 * * * * * *