为何Python中import正常但函数内exec执行后无法访问变量?
问题原因与解决方案:exec在函数内无法访问动态创建的变量
原因分析
- 在函数内部使用
exec()时,默认会操作函数的局部命名空间,但Python的函数局部变量是编译阶段就确定的,exec()动态创建的变量不会被自动加入到函数的局部符号表中,直接访问就会触发NameError。 - 在解释器中逐行执行时,代码运行在全局命名空间,
exec()创建的变量直接进入全局命名空间,因此能正常访问。 import data能正常访问,是因为模块data有独立的命名空间,testd是该模块的属性,和当前执行环境的命名空间无关。
解决方案
方法1:指定exec使用全局命名空间
修改exec()调用,让变量存入全局命名空间,函数内即可直接访问:
from pathlib import Path def read_data(): path = Path.cwd() / "data.py" text = path.read_text() print(f"{text=}") exec(text, globals()) return testd
方法2:用自定义字典存储exec的变量
创建独立字典作为exec()的命名空间,避免污染全局环境,之后从字典中取出目标变量:
from pathlib import Path def read_data(): path = Path.cwd() / "data.py" text = path.read_text() print(f"{text=}") local_namespace = {} exec(text, globals(), local_namespace) return local_namespace['testd']
方法3:改用importlib动态导入模块(推荐)
既然data.py是合法Python模块,用官方的importlib动态导入比exec()更安全规范:
import importlib.util from pathlib import Path def read_data(): module_path = Path.cwd() / "data.py" spec = importlib.util.spec_from_file_location("data", module_path) data = importlib.util.module_from_spec(spec) spec.loader.exec_module(data) return data.testd
内容的提问来源于stack exchange,提问作者Rodney Price
相关产品推荐
相关产品推荐

