Python使用exec()运行递归代码无法获取返回结果的问题求解
问题根因
你遇到的两个问题本质都是作用域配置错误:
- 最初
exec(code, {}, loc)递归失效:你给exec传入的全局作用域是空字典,递归函数定义后名称仅存在局部作用域loc中,函数执行时会优先从绑定的全局作用域查找自身名称,找不到就会报错。 - 包裹foo后拿不到result:你把原代码的执行逻辑封装在了foo函数内部,原代码里赋值的
result是foo的局部变量,exec的返回字典只能拿到顶层作用域的变量,自然找不到result。
方案1:修改包裹函数适配现有逻辑
如果你要保留包裹函数的写法,只需要修改包裹逻辑,把foo内部的result返回并赋值给顶层的result即可:
import textwrap def wrap(s): return "def foo():\n" \ "{}\n" \ "result = foo()".format(textwrap.indent(s, ' ' * 4))
修改后执行包裹后的代码,loc字典中就能正常获取到result的值。
方案2(更优):无需包裹,直接统一作用域
根本不需要额外包裹代码,只需要把同一个自定义字典同时传给exec的globals和locals参数即可同时解决递归支持和结果获取的问题,写法更简洁:
def codeTester(code): # 自定义字典同时作为全局和局部作用域 runtime_scope = {} try: exec(code, runtime_scope, runtime_scope) except Exception as e: # 你的异常处理逻辑 raise e # 直接从作用域字典取result即可 result = runtime_scope['result'] return result
方案说明
- 自定义字典同时作为全局和局部作用域,递归函数定义后名称会存入该字典,函数执行时从全局作用域可以正常找到自身名称,递归可正常运行
- 原代码中赋值的
result会直接存在该字典中,无需额外处理即可直接获取 - 不要使用函数内置的
locals()传参:Python函数内部的locals()返回的是局部变量的只读快照,对其的修改不会生效,也无法同步exec的执行结果,自定义空字典没有这个问题。
内容的提问来源于stack exchange,提问作者user1922979
相关产品推荐
相关产品推荐

