【问题标题】:module name in sys.modules and globals()sys.modules 和 globals() 中的模块名称
【发布时间】:2011-08-19 22:02:38
【问题描述】:

如果我导入一个模块,模块名称会同时出现在sys.modulesglobals() 中。如果我再次删除它,它会从globals() 中删除,但仍驻留在sys.modules 中。为什么会这样?

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

【问题讨论】:

  • 可以从 sys.modules 中删除模块,del sys.modules['mymodule'],这有时很有用。

标签: python


【解决方案1】:

就像任何其他 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 仅用于导入语句。您可以从 sys.modules 中删除一个模块,以便 Python 在下次导入时重新加载它。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      因为 Python 将模块缓存在 sys.modules 中,以防止(昂贵、缓慢的)模块查找过程运行得过多。

      如果需要,可以从sys.modules 中删除模块,尽管reload 也可以工作。


      更详细地说,当您import mymodule 发生各种事情时。在我的脑海中,假设mymodule 不是解释器可执行文件中内置的模块之一:

        1234563这也会查看当前目录、sys.path 和其他位置。
      1. 对由此定位的文件进行词法分析、解析和编译(如有必要)成解释器字节码。

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

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

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

      (根据我对import 背后机制的记忆,以上是一个非常粗略的近似值。它可能在重要和微妙的方面是错误的。)

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

      【讨论】:

      • 但是如果我通过执行del mymodule删除名称绑定,我将它从命名空间中删除,这样我就可以执行import mymodule,这两个步骤一起相当于执行reload(mymodule),对吧?
      • @Hongbo: wrong: import 先在sys.modules 中查看是否已经导入了模块。如果有,它只会为您提供上次导入模块时创建的模块对象。由于del mymodule 不会从sys.modules 中删除模块对象,因此重新导入它只会将名称重新绑定到sys.modules 中的对象。
      • @Hongbo:如果你想让它重新导入模块,请reload(module)。等效地,将其从sys.modules 中删除,然后从import 中删除。
      • 非常感谢,katrielalex。你的回答帮助我解决了module name in sys.modules and globals()@ 帖子中的谜题
      猜你喜欢
      • 2022-12-20
      • 2018-01-24
      • 2010-12-29
      • 2018-09-04
      • 2012-02-27
      • 2020-04-04
      • 1970-01-01
      相关资源
      最近更新 更多