为什么`sys.modules.keys()`包含来自`import ... as`的名字?

时间:2014-01-13 16:10:44

标签: python

假设我按如下方式导入模块:

import os as OSMOD

然后想找到工作目录

OSMOD.getcwd()

OSMOD现在是os的替代品,使用os将无效。这都是花花公子,对我有用。但是,我发现有些奇怪的东西。如果我像上面那样导入os,然后获取所有导入模块的列表,那么会发生以下情况:

>>> import sys
>>> import os as OSMOD
>>> modList = sys.modules.keys()
>>> print "os" in modList
True
>>> print "OSMOD" in modList
False

这不是我的预期。根据文档modules.keys() only lists the imported modules。对我来说,这意味着它应该列出OSMOD

为什么sys.modules.keys()不包含OSMOD而不是os

此外,是否有sys.modules.keys()的等效列表,其中包含OSMOD

编辑:我想这里更大的问题是理由。如果Python要将os作为模块,为什么要删除引用呢? (即,为什么os.getcwd()OSMOD.getcwd()都不起作用?)

或者,更简单地说,为什么import os as OSMOD的行为与import os后跟OSMOD = os的行为相同?

5 个答案:

答案 0 :(得分:9)

因为模块的名称是os。你做了import osas OSMOD只是告诉Python将该模块分配给模块命名空间中的名称OSMOD

sys.modules是导入模块的缓存,用于防止模块多次导入。如果它将导入的模块存储在OSMOD下,则另一个执行import os的模块将再次导入该模块。

答案 1 :(得分:1)

sys.modules包含导入模块的真实名称。但是,包含使用as <name>下导入的名称。

换句话说,当你这样做时:

import os as OSMOD

os模块实际上是导入的。但是,它以OSMOD的名称导入。

尽管如此,名称os仍会添加到sys.modules,因为这是导入模块的真实名称。 OSMOD虽然已添加,因为它不是模块。相反,它是导入的os模块的备用名称。

答案 2 :(得分:1)

来自documentation

  

基本的import语句(no from子句)分两步执行:

     
      
  • 找到一个模块,必要时加载并初始化
  •   
  • 在本地命名空间中为import语句的范围定义一个或多个名称。
  •   

特别是,第二步意味着:

  

如果成功检索到请求的模块,它将以三种方式之一在本地命名空间中可用:

     
      
  • 如果模块名称后跟as,则后面的名称将直接绑定到导入的模块。
  •   

这意味着您的模块可用的名称将显示在locals()globals()中:

>>>import sys as X
>>> locals()['X']
<module 'sys' (built-in)>
>>> 

答案 3 :(得分:1)

您似乎对模块对象以及对该对象的引用感到困惑。 sys.modules['os']是对模块对象的一个引用,OSMOD是另一个。

当您使用语句import os as OSMOD时,Python确保将os模块加载到内存中(使用sys.modules字典作为缓存)然后创建对模块对象的引用你当前的命名空间因为您使用as OSMOD Python看到您想要使用名称OSMOD并将模块绑定到该名称。

如果您使用import os,那么Python默认为与模块名称相同,因此它会将对象绑定到本地命名空间中的os

你绝不会受到限制。您仍然可以将同一个对象绑定到其他名称:

os = OSMOD

会给你另一个对同一模块对象的引用。

请记住,您的模块全局命名空间仅对模块是全局的;其他模块看不到相同的名称。因此,您希望控制在其中定义的名称。也许您希望将名称os完全用于 else 。以下是合法的:

os = 'Ozzy Santana'
import os as OSMOD

我希望os仍然绑定到字符串,而不是模块。

同时,我的Python项目中的另一个模块仍然可以使用import os并让os引用该模块;它不会在第一个模块中看到绑定到os的字符串。

答案 4 :(得分:0)

您导入了os。然后你把它放到名字OSMOD。以下是发生的事情的简单说明:

import os
OSMOD = os
del os

导入的模块仍然是os,而不是osmod,因此它将是sys.modules.keys()中列出的模块。

是的,type(OSMOD)是一个模块,因为它绑定到模块对象。