如何将范围扩展到执行函数?

How to extend scope to an exec'd function?

我有一个包含多个函数定义的模块对象。这是一个简化的例子。

源代码(组成模块“my_module”)

def functionA():
    print("hello")

def functionB():
    functionA()
    print("world")

该模块是用 imp 构建的(我知道它已贬值,但我的应用程序仍在 python 3.5)

ast_node = parse(source)
byte_code = compile(ast_node, 'my_module', 'exec')
my_module = imp.new_module('my_module')
exec(byte_code, __builtins__, my_module.__dict__)

我正在尝试 运行 functionB() 使用 exec 并传入完整模块 __dict__ 作为本地字典。 (我也尝试过将它作为全局字典传递,但没有任何运气)

exec("functionB()", None, my_module.__dict__)

我看到的错误是NameError: name 'functionA' is not defined

是否可以将局部(甚至全局)作用域扩展到执行函数?

您不需要“扩展范围”。您的问题是您在错误的名称空间中做事。当您执行模块的代码时:

exec(byte_code, __builtins__, my_module.__dict__)

当您应该将模块的命名空间用作全局变量时,您正在使用内置命名空间作为全局变量:

exec(byte_code, my_module.__dict__)

然后模块的函数将具有正确的全局命名空间。目前,他们都在使用内置命名空间作为他们的全局命名空间。

此外,不要将 __builtins__ 用于内置命名空间。它是一个实现细节,它甚至不会像您想象的那样工作——它的价值在不同的上下文中是不同的。有时它被设置为 builtins 模块本身,而不是该模块的字典。相反,import builtins 并在需要内置字典时使用 builtins.__dict__