如何检查是否已导入python模块?


91

如何检查我是否在代码中的某个位置导入了模块?

 if not has_imported("somemodule"):
     print('you have not imported somemodule')

我想检查是否已经导入模块的原因是因为我有一个我不想导入的模块,因为有时会弄乱我的程序。


只需将raise SystemError()(或您选择的其他例外方式)放在您不想导入的模块的顶部。如果你实际导入它的地方,你的程序将抛出一个回溯并退出。
larsk's

无论如何,仅导入模块如何会弄乱您的程序?听起来不太可能。
比尔·伍德格

1
@BillWoodger:也许该模块更改了您不想更改的全局状态
马丁·彼得斯

@MartijnPieters Yoiks。而且导入声音是如此中性。
比尔·伍德格

Answers:


122

测试sys.modules字典中的模块名称:

import sys

modulename = 'datetime'
if modulename not in sys.modules:
    print 'You have not imported the {} module'.format(modulename)

从文档中:

这是将模块名称映射到已经加载的模块的字典。

请注意,import语句有两件事:

  1. 如果模块以前从未导入过(=中不存在= sys.modules),则将其加载并添加到sys.modules
  2. 在当前名称空间中绑定1个或多个引用模块对象或模块名称空间成员的对象的名称。

该表达式modulename not in sys.modules测试步骤1是否已发生。测试步骤2的结果需要知道使用了什么确切的import语句,因为它们设置了不同的名称来引用不同的对象:

  • import modulenamemodulename = sys.modules['modulename']
  • import packagename.nestedmodulepackagename = sys.modules['packagename'](无论您添加多少个附加级别)
  • import modulename as altnamealtname = sys.module['modulename']
  • import packagename.nestedmodule as altnamealtname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectnameobjectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenamenestedmodulename = sys.modules['packagename.nestedmodulename'](仅当此导入之前nestedmodulenamepackagename命名空间中没有命名对象时,此刻嵌套模块的附加名称才会添加到父包命名空间)
  • from somemodule import objectname as altnamealtname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnamealtname = sys.modules['packagename.nestedmodulename'](仅当此导入之前nestedmodulenamepackagename命名空间中没有命名对象时,此刻嵌套模块的附加名称才会添加到父包命名空间)

您可以测试给定名称空间中是否存在与导入对象绑定的名称:

# is this name visible in the current scope:
'importedname' in dir()

# or, is this a name in the globals of the current module:
'importedname' in globals()

# or, does the name exist in the namespace of another module:
'importedname' in globals(sys.modules['somemodule'])

这仅告诉您名称存在(已绑定),而不是名称是指特定模块还是该模块中的对象。sys.modules如果您需要排除此后名称已完全设置为其他名称,则可以进一步自省该对象或测试其是否与所提供的对象相同。


1
这是检查函数中所需软件包的最佳方法吗?也就是说,某些功能需要numpy包装-import sys在功能内部使用的最佳方法是检查它是否已导入?所谓“最佳”,是指对性能的影响,import sys每次调用该函数时都会调用它。谢谢您
困惑

@Confounded,如果您担心的话,可以直接在函数之外导入sys。这绝不import sys是昂贵的。sys始终存在,默认情况下已加载。但是对于可选软件包:只需导入package即可ImportError如果未安装该软件包,则捕获异常,并设置一个标志,指示导入成功后已安装该软件包。之后,您可以使用该标志来通知您对可选依赖项的使用。
马丁·彼得斯

@Confounded该name in sys.modules测试仅在您不想导入时才有用。
马丁·彼得斯

24

对于sys.modules接受的答案,我要加一个警告,以在导入时重命名模块要小心:

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True

18

使用sys.modules测试是否已导入模块(我以unicodedata为例):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True

5

sys.modules 包含解释器当前实例中任何地方使用的所有模块,因此如果导入到任何其他Python模块中就会显示出来。

dir() 检查名称是否在当前名称空间中定义。

2的组合比每个​​单独的组合更安全,并且只要您没有定义copy自己就可以使用。

if ('copy' in sys.modules) and ('copy' in dir()):

0
if "sys" not in dir():
  print("sys not imported!")

那只会检查模块是否在当前名称空间中导入。也sys可以是任何东西,而不仅仅是模块。
vaultah
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.