python散装笔记——106: 使用 exec 和 eval 动态执行代码

liftword10小时前技术文章1


Argument

Details

expression

表达式代码字符串或 code 对象

object

语句代码字符串或 code 对象

globals

用于全局变量的 dictionary。如果未指定 locals,该字典也将用于 locals。如果省略,则使用调用作用域的 globals()

locals

用于局部变量的映射对象。如果省略,则使用为 globals 传递的映射对象。如果两者都省略,则调用作用域的 globals()locals() 将分别用于 globalslocals

1: 使用 exec、eval 或 ast.literal_eval 执行未受信任用户提供的代码

无法使用 evalexec 安全地执行来自不信任用户的代码。即使是 ast.literal_eval 也容易导致解析器崩溃。有时可以防范恶意代码的执行,但并不排除解析器或标记符号生成器彻底崩溃的可能性。

要对不信任的用户执行的代码进行评估,您需要使用一些第三方模块,或者用 Python 编写自己的解析器和虚拟机。

2: 使用 ast.literal_eval 评估包含 Python 字面量的字符串

如果字符串中包含 Python 字面量,如字符串、浮点数等,可以使用 ast.literal_eval 代替 eval 来求值。这样做的另一个好处是只允许使用特定的语法。

>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)

然而,这对执行不信任用户提供的代码并不安全,而且使用精心制作的输入使解释器崩溃也是轻而易举的事

>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5] 21358 segmentation fault (core dumped) python3

这里的输入是一个重复了一百万次的 () 字符串,这会导致 CPython 解析器崩溃。CPython 开发人员不会将解析器中的错误视为安全问题。

3: 使用执行程序评估语句

>>> code = """for i in range(5):\n print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!

4: 使用 eval 计算表达式

>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20

5: 预编译表达式以对其进行多次评估

内置函数 compile 可用于将表达式预编译为代码对象,然后将代码对象传递给 eval。这将加快重复执行已求值代码的速度。编译 “的第三个参数必须是字符串”eval"。

>>> code = compile('a * b + c', '', 'eval')
>>> code
<code object  at 0x7f0e51a58830, file "", line 1>
>>> a, b, c = 1, 2, 3
>>> eval(code)
5

6: 使用自定义全局项用 eval 评估表达式

>>> variables = {'a': 6, 'b': 7}
>>> result = eval('a * b', variables)
>>> print(result)
42

此外,这样代码就不会意外地引用外部定义的名称:

>>> eval('variables')
{'a': 6, 'b': 7}
>>> eval('variables', globals=variables)
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 1, in 
NameError: name 'variables' is not defined

例如,使用 defaultdict 可以将未定义的变量设置为零:

>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables) # note that 'c' is not explicitly defined
0

相关文章

深入了解Python 解析器 - CPython

前言Python 是一门广泛使用的编程语言,而 CPython 则是它最常用的解析器之一。作为 Python 的官方参考实现,CPython 在解释和执行 Python 代码方面扮演着重要的角色。本文...

什么是Python中的DSL领域特定语言?

在Python中,DSL是指专门针对特定领域或者是解决某个特定领域问题所设计的语言,这个操作通常用于解决某个特定领域的问题,而不是通用的编程操作,DSL可以通过Python的语法以及其语言特性来实现,...

详细介绍一下Python中的BeautifulSoup库的使用?

BeautifulSoup是一个流行的Python爬虫库,主要的作用是用于从HTML和XML文档中提取数据。以其简单易用的API和强大的功能受到广泛的使用,特别是在Web爬虫和数据解析的场景中。下面我...

使用 Python 开发一个 Python 解释器

原文地址:https://python.plainenglish.io/introduction-to-creating-interpreter-using-python-c2a9a6820aa0原文...

【Python】性能加速之解析器加速Pypy 库使用说明

Pypy 简介#python##python自学#PyPy是一个高性能的Python解释器,它使用JIT(即时编译)技术来加速Python代码的执行速度。PyPy支持所有的标准Python库,并且...