Python中从编译字符串返回函数时出现NameError问题排查
问题分析与解决方案
错误原因
在函数内部使用exec执行代码时,Python的函数局部作用域是静态解析的,exec无法动态将新定义的函数f添加到当前函数的局部命名空间中,直接返回f自然会触发NameError。
解决方法
使用自定义的命名空间字典来承接exec执行后的变量,再从字典中取出目标函数,这是最安全可控的方式:
import typing as t def compile_functions() -> t.Callable: code = """def f():\n\treturn 1""" # 自定义命名空间,用于存储exec执行后生成的变量 func_namespace = {} # 将代码执行到自定义命名空间中 exec(code, func_namespace) # 从命名空间中取出定义好的函数f return func_namespace['f']
如果需要用到之前编译好的compiled对象,也可以替换成exec(compiled, func_namespace),效果一致。
额外说明
不要尝试将exec的结果直接注入到函数局部作用域(比如用locals()作为命名空间),因为Python对局部变量的静态优化会导致这种方式无法生效,甚至引发不可预期的问题。
内容的提问来源于stack exchange,提问作者nestor556
相关产品推荐
相关产品推荐

