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
上下文