为什么动态加载模块的函数取决于模块的存储位置?

时间:2014-06-27 10:29:37

标签: python python-2.7

关注this answer,我使用imp.new_moduleexec来动态加载模块并从中提取函数。但是,当我将模块存储在局部变量中时,它的函数会被破坏。这是一个例子:

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执行此操作会产生Nonecodepad。取消注释global mod行,使mod全局后,该函数按预期工作并打印42:codepad

我错过了什么?当模块存储在局部变量中时,为什么行为会发生变化?

1 个答案:

答案 0 :(得分:1)

mod模块是本地模块,未在其他任何地方引用。与Python中的所有其他对象一样,这意味着在main退出时会清除它。通过使其成为全局变量,保留对模块对象的引用。

清理模块时,所有全局变量都设置为None(这样做是为了尽早打破参考周期,设置为None是一种优化,可以防止由于字典调整大小而导致过度重复) 。 func对象仍然具有对模块全局字典的引用,因此现在看到a绑定到None

导入模块的普通过程会在sys.modules中添加对模块对象的引用,使模块保持活动状态直到解释器关闭。

(在Python 3.4中,根据Safe Object Finalization,全局变量不再反弹到None(在大多数情况下);请参阅PEP 442)。