为何使用exec执行代码时函数无法调用另一个函数?
为何直接调用bar函数正常,但foo内部调用bar却报NameError?
问题代码
py = """ a = 1 print (f'before all {a=}') def bar(n): print(f'bye {n=}') def foo(n): print(f'hello {n=}') bar(n) bar ('just works') foo ('sara') """ loc = {} glo = {} bytecode = compile(py, "script", "exec") exec(bytecode, glo, loc)
运行结果
before all a=1 bye n='just works' hello n='sara' Traceback (most recent call last): File "/home/bla-bla/pythonProject/main_deco2.py", line 43, in <module> exec(bytecode, glo, loc) File "script", line 13, in <module> File "script", line 10, in foo NameError: name 'bar' is not defined
原因分析
核心是Python的名字查找规则和exec传入的双命名空间差异导致的:
- 顶层调用
bar('just works')时,Python会优先在**当前局部命名空间(即你传入的loc字典)**里查找bar,此时bar已经被定义并存入loc,所以能正常执行。 - 但函数
foo在定义时,它的全局作用域被绑定到了你传入的glo字典。当foo内部调用bar时,Python会去foo绑定的全局命名空间(glo)里查找,而bar只被存入loc、未进入glo,所以触发NameError。
解决方法
最直接的方案是统一命名空间,让全局和局部使用同一个字典:
# 方法1:只传全局命名空间,局部会默认复用全局 exec(bytecode, glo) # 方法2:显式传入同一个字典作为全局和局部 namespace = {} exec(bytecode, namespace, namespace)
内容的提问来源于stack exchange,提问作者k31
相关产品推荐
相关产品推荐

