Python exec 上下文

Python exec 上下文

昨天在写一个项目的时候,需要动态执行代码,在动态执行的代码中进行了赋值,但下下文中调用对象,提示未定义,于是有了以下的探索。

1 exec()函数介绍

源自:菜鸟教程-Python3

1-1 用法

exec(object[, globals[, locals]])

简单来说,执行object中的代码,后面俩参数可以用来传递变量(传递命名空间)

1-2 参数

  • object:必选参数,表示需要被指定的 Python 代码。它必须是字符串或 code 对象。如果 object 是一个字符串,该字符串会先被解析为一组 Python 语句,然后再执行(除非发生语法错误)。如果 object 是一个 code 对象,那么它只是被简单的执行。
  • globals:可选参数,表示全局命名空间(存放全局变量),如果被提供,则必须是一个字典对象。
  • locals:可选参数,表示当前局部命名空间(存放局部变量),如果被提供,可以是任何映射对象。如果该参数被忽略,那么它将会取与 globals 相同的值。

1-3 返回值

exec 返回值永远为 None。

2 exec()的上下文

简而言之,如果exec()代码在非全局作用域,则其上下文是独立的,相当于进入了一个交互式解释器(bash中的python那样)

但相同作用域下exec()中的上下文是相同的

通过下面几个例子可以很容易地理解这个概念

2-1 示例

2-1-1 在全局作用域下使用

>>> a = 13
>>> exec('b = a + 1')
>>> print(b)
14

可以看到,在全局作用域下,exec()的上下文与全局上下文相同

2-1-2 在非全局作用域下使用

>>> def test():
...     a = 13
...     exec('b = a + 1')
...     print(b)
...
>>> test()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in test
NameError: global name 'b' is not defined
>>>

可以看到,在非全局作用域下,exec()的上下文与 exec()代码所在的上下文不同,且在执行结束后,没有同步上下文

2-1-3 在相同作用域下使用

>>> def test():
...     a = 13
...     exec('b = a + 1')
...     exec('print(b)')
...
14

可以看到,在相同作用域下,exec() 的上下文相同

2-2 同步exec()和当前作用域的上下文

def test(module):
    exec_scope = {"module": module}
    exec(f"module = {module}()", exec_scope)  # 实例化module对象
    exec(f"test_result = module.test()", exec_scope)  # 执行module的test函数 
    test_result = exec_scope['test_result']  # 从exec上下文中获取执行结果

可以通过{}字典进行上下文传递,将需要的变量传入/传出exec上下文

posted @ 2021-05-13 00:07  R3col  阅读(313)  评论(0编辑  收藏  举报