关注this answer,我使用imp.new_module
和exec
来动态加载模块并从中提取函数。但是,当我将模块存储在局部变量中时,它的函数会被破坏。这是一个例子:
import imp
mod = None
func = None
code = """
a = 42
def func():
print a
"""
def main():
#global mod
global func
mod = imp.new_module("modulename")
exec code in mod.__dict__
func = mod.func
main()
func()
使用Python 2.7.3执行此操作会产生None
:codepad。取消注释global mod
行,使mod
全局后,该函数按预期工作并打印42:codepad。
我错过了什么?当模块存储在局部变量中时,为什么行为会发生变化?
答案 0 :(得分:1)
mod
模块是本地模块,未在其他任何地方引用。与Python中的所有其他对象一样,这意味着在main
退出时会清除它。通过使其成为全局变量,保留对模块对象的引用。
清理模块时,所有全局变量都设置为None
(这样做是为了尽早打破参考周期,设置为None
是一种优化,可以防止由于字典调整大小而导致过度重复) 。 func
对象仍然具有对模块全局字典的引用,因此现在看到a
绑定到None
。
导入模块的普通过程会在sys.modules
中添加对模块对象的引用,使模块保持活动状态直到解释器关闭。
(在Python 3.4中,根据Safe Object Finalization,全局变量不再反弹到None
(在大多数情况下);请参阅PEP 442)。