Python:模块在传递给 exec(...) 的代码块中的作用域中丢失 为什么当调用 z 函数时 helpers 模块消失了?我为什么要这样做?不太理想的解决方法:

问题描述

代码块中直接调用时,调用导入的函数 helpers.test_func(...) 会成功。

但由于此异常而失败:

  File "<string>",line 11,in <module>
  File "<string>",line 8,in z
NameError: name 'helpers' is not defined

间接调用时,通过函数z(),也在块中定义

code = """        
from my_proj import helpers

helpers.test_func("a")    

def y():
    print("b")

def z():
    helpers.test_func("c")

y()
z()    
"""

def test_func(v1):    
    print("--->{}".format(v1))

def test():
    exec(code)

if __name__ == '__main__':
    test()

代码输出

--->a
b

File "<string>",in <module>
File "<string>",in z
NameError: name 'helpers' is not defined

为什么当调用 z 函数helpers 模块消失了?

我为什么要这样做?

我正在尝试实现一个工具,该工具加载函数文件 (a_file.py),其中定义了函数,并且我想从该工具调用函数。像这样:

_locals = {}
_globals = {}
eval(code_of_file,_globals,_locals)

f = _locals["func_defined_in_scope_of_file"]

f()  # <---- this fails with the same NameError as above

上面的例子比较简单,如果失败了,我相信如果我能解决上面的问题,我就可以使用相同的解决方案。

不太理想的解决方法

函数 z 的主体中添加 from dry_pipe import helpers 解决了问题,但并不优雅

code = """        
from dry_pipe import helpers 

helpers.test_func("a")    
def y():
    print("b")

def z():
    from dry_pipe import helpers    
    helpers.test_func("c")

y()
z()    
"""

解决方法

您的范围有问题。 exec 函数在“当前”范围内运行,因此您应该将 globals() 作为第二个参数传递给 exec 函数(以查看全局属性)。我已经写了一个工作示例,请在下面查看。 ((不得不说,exec 函数真的不推荐使用))

my_proj.py:

class Helper:
    @classmethod
    def test_func(cls,a):
        print("TEST FUNC - {}".format(a))

test.py:

code = """
from my_proj import Helper as helpers

helpers.test_func("a")

def y():
    print("b")

def z():
    helpers.test_func("c")

y()
z()
"""

def test_func(v1):
    print("--->{}".format(v1))

def test():
    exec(code,globals())

if __name__ == '__main__':
    test()

输出:

>>> python3 test.py 
TEST FUNC - a
b
TEST FUNC - c