如何在Python eval中添加上下文函数?报错求解决方案
问题原因
函数g在定义时会绑定自身的__globals__属性,指向定义它时的全局命名空间。运行eval('g(1)', globals() | {'my_func': add})时,虽然给eval传了包含my_func的命名空间,但g内部查找my_func时,只会去它自己绑定的__globals__里找,不会用eval传入的那个,所以才会报NameError。
解决方案(无需修改
add和g) 方法一:临时修改函数的全局命名空间
直接临时修改g的__globals__属性,把my_func注入进去,执行完再还原,避免污染全局环境:
def add(x, y): return x + y def g(x): u = my_func(x, 4 ** x) return my_func(u, u // 2) # 保存原有my_func(防止之前存在同名变量) original_my_func = g.__globals__.get('my_func') try: # 将add注入到g的全局命名空间 g.__globals__['my_func'] = add # 执行g(1) result = eval('g(1)') print(result) # 输出7 finally: # 还原命名空间 if original_my_func is not None: g.__globals__['my_func'] = original_my_func else: del g.__globals__['my_func']
方法二:在目标命名空间重定义函数
如果不想修改原函数的属性,可以保存g的源码,在包含my_func的命名空间里重新定义g,这样新的g会自动绑定包含my_func的全局空间:
def add(x, y): return x + y # 保存g的源码(和原函数代码完全一致) g_source = """ def g(x): u = my_func(x, 4 ** x) return my_func(u, u // 2) """ # 在包含my_func的自定义命名空间里执行g的定义 custom_globals = globals().copy() custom_globals['my_func'] = add exec(g_source, custom_globals) # 取出新定义的g g_custom = custom_globals['g'] print(g_custom(1)) # 输出7
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

