2011-08-19 37 views
9

如果我导入模块,则模块名称将显示在sys.modulesglobals()之间。如果我再次删除它,它将从globals()中删除,但仍位于sys.modules。为什么这样?sys.modules和globals中的模块名称()

import mymodule 
'mymodule' in globals() # True 
'mymodule' in sys.modules # True 
del mymodule 
'mymodule' in globals() # False 
'mymodule' in sys.modules # Still True, why? 

我还发现了以下区别:

from mypackage import mymodule 
'mypackage' in sys.modules   # True 
'mymodule' in sys.modules   # False ! 
'mypackage.mymodule' in sys.modules # also True ! 

而答案是互补的为globals()

'mypackage' in sys.modules   # False 
'mymodule' in sys.modules   # True 
'mypackage.mymodule' in sys.modules # False 
+0

它*是*可能从sys.modules,'del sys.modules ['mymodule']'中删除模块,这有时很有用。 – SingleNegationElimination

回答

4

就像任何其他Python对象一样,模块会一直存在,直到没有更多的引用为止。换句话说,sys.modules的行为像一个普通的字典,并

import mymodule 
lst = {mymodule.__name__: mymodule} 
'mymodule' in globals() # True 
'mymodule' in lst   # True 
del mymodule 
'mymodule' in globals() # False 
'mymodule' in lst   # Still True 

sys.modules只征询import语句。您可以从sys.modules中删除一个模块,以使Python在下次导入时重新加载它。

3

因为Python在sys.modules缓存模块,以防止(昂贵的,慢)正在运行的模块寻找过程超过了必要的范围。

如果需要,可以从sys.modules删除模块,但reload也可以。


更详细地说,当你import mymodule各种事情发生。关闭我的头顶,并假设mymodule不内置于解释器可执行模块之一:

  1. 的解释程序运行一些复杂的代码,以找到包含mymodule文件(这可能是mymodule.pymymodule.pyc ,或mymodule.pyd - 或者其他的东西,我没有想到,这通过当前目录,sys.path,以及其他地方看起来

  2. 因此找到的文件是lexed,解析和编译如果有必要的话)解释器字节码。

  3. 编译模块被执行,给出一个模块对象。

  4. 模块对象被插入到sys.modules中。

  5. 模块对象绑定到import语句中指定的局部变量。

(以上是一个非常粗略的估计基于我记得背后import的机制。这是一个在重要和微妙的方式可能是错误的。)

注意,那么,结合模块对象本地名称实际上只是实际导入过程中的一小部分。通过执行del mymodule删除名称绑定不会影响导入的其余部分。

+1

但是,如果我通过执行'del mymodule'来删除名称绑定,我将它从命名空间中删除,以便我可以执行'import mymodule',这两个步骤一起等同于执行'reload(mymodule)',对吧? – HongboZhu

+1

@洪波:错误:'import'在sys.modules'中查找是否已经导入模块。如果有,它只会给你它上次导入模块时所做的模块对象。由于'del mymodule'不会将模块对象从'sys.modules'中删除,重新导入它只会将名称重新绑定到'sys.modules'中的对象。 – katrielalex

+1

@Hongbo:如果你想重新导入模块,请执行'reload(module)'。等同地,从'sys.modules'中删除它,然后'导入'它。 – katrielalex

4

del删除适当范围内名称的绑定;它与模块本身无关。

sys.modules保留所有已加载模块的列表,而不管它们是否绑定到程序中的任何名称。