使用exec函数传入局部命名空间时import导入库失效如何解决?
exec指定局部命名空间时导入模块报错的解决方法
问题根因
当你给exec同时传入自定义全局命名空间(第二个参数)和局部命名空间(第三个参数)时,Python会遵循以下作用域规则:
- 执行代码时定义的所有变量、导入的模块、声明的函数默认都会存入你传入的局部命名空间
- 代码内部声明的函数访问非本地变量时,只会查找函数自身的局部作用域和
exec传入的全局命名空间,不会查找自定义的局部命名空间
你的场景中import math被存入了loc局部命名空间,你传入的全局命名空间里只有n=10没有math,因此fun函数内部访问math.pi时就会触发NameError。
解决方案
方案1:共用同一个命名空间(最简方案)
不需要拆分全局和局部命名空间,直接用同一个字典存储所有exec执行产生的变量,执行完成后直接从该字典中取出dd即可:
namespace = dict(n = 10) exec(codeObejct, namespace) dd = namespace["dd"]
方案2:将依赖模块传入全局命名空间
如果必须拆分全局和局部命名空间,可以提前在外部导入依赖的模块,放入exec的全局命名空间中:
import math loc = {} exec(codeObejct, dict(n = 10, math=math), loc) dd = loc["dd"]
方案3:修改代码字符串的导入声明
如果不能修改exec的传参逻辑,可以给代码字符串中的导入语句加上global声明,强制导入的模块存入全局命名空间:
codeRule = """global math import math def fun (n): data = n data = data * math.pi print(data) return data dd = fun(n)""" codeObejct = compile(codeRule, 'sumstring', 'exec') loc = {} exec(codeObejct, dict(n = 10), loc) dd = loc["dd"]
内容的提问来源于stack exchange,提问作者NIKHIL SUTHAR
相关产品推荐
相关产品推荐

