如何在不导入的情况下检查 Python 模块是否存在

新手上路,请多包涵

如果不导入 Python 模块,我怎么知道它是否存在?

导入可能不存在的东西(不是我想要的)会导致:

 try:
    import eggs
except ImportError:
    pass

原文由 yarbelk 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

长话短说)使用 importlib.util.find_spec(module_name) (Python 3.4+)

Python2: imp.find_module

要检查 导入 是否可以在 Python 2 中找到某些内容,请使用 imp

 import imp
try:
    imp.find_module('eggs')
    found = True
except ImportError:
    found = False

要找到带点的导入,您需要做更多的事情:

 import imp
try:
    spam_info = imp.find_module('spam')
    spam = imp.load_module('spam', *spam_info)
    imp.find_module('eggs', spam.__path__) # __path__ is already a list
    found = True
except ImportError:
    found = False

您还可以使用 pkgutil.find_loader (与 Python 3 部分大致相同:

 import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None

蟒蛇3

Python 3 ≤ 3.3: importlib.find_loader

您应该使用 importlib 。我开始这样做:

 import importlib
spam_loader = importlib.find_loader('spam')
found = spam_loader is not None

我的期望是,如果你能为它找到一个装载机,那么它就存在。你也可以更聪明一点,比如过滤掉你将接受的装载机。例如:

 import importlib
spam_loader = importlib.find_loader('spam')
# only accept it as valid if there is a source file for the module - no bytecode only.
found = issubclass(type(spam_loader), importlib.machinery.SourceFileLoader)

Python 3 ≥ 3.4: importlib.util.find_spec

在 Python 3.4 importlib.find_loader 中弃用了 Python 文档,取而代之的是 importlib.util.find_spec 。推荐的方法是 importlib.util.find_spec 。还有其他像 importlib.machinery.FileFinder ,如果您要加载特定文件,这很有用。弄清楚如何使用它们超出了本文的范围。

 import importlib
spam_spec = importlib.util.find_spec("spam")
found = spam_spec is not None

这也适用于相对导入,但你必须提供起始包,所以你也可以这样做:

 import importlib
spam_spec = importlib.util.find_spec("..spam", package="eggs.bar")
found = spam_spec is not None
spam_spec.name == "eggs.spam"

虽然我确定这样做是有原因的 - 但我不确定它会是什么。

警告

当试图找到一个子模块时,它将导入父模块(对于上述 所有 方法)!

 food/
  |- __init__.py
  |- eggs.py

## __init__.py
print("module food loaded")

## eggs.py
print("module eggs")

were you then to run
>>> import importlib
>>> spam_spec = importlib.util.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')

欢迎发表评论来解决这个问题

致谢

  • @rvighne 用于 importlib
  • @lucas-guido 用于 Python 3.3+ 弃用 find_loader
  • @enpenax 用于 Python 2.7 中的 pkgutils.find_loader 行为

原文由 yarbelk 发布,翻译遵循 CC BY-SA 4.0 许可协议

Python 3 >= 3.6: ModuleNotFoundError

ModuleNotFoundError 已在 Python 3.6 中引入,可用于此目的:

 try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass

当找不到 模块或其父模块之一 时会引发错误。所以

try:
    import eggs.sub
except ModuleNotFoundError as err:
    # Error handling
    print(err)

如果找不到 eggs 模块,将打印一条看起来像 No module named 'eggs' 的消息;但它会打印类似 No module named 'eggs.sub' 如果只有 sub 模块找不到,但 eggs 包可以找到。

有关 ModuleNotFoundError 的更多信息,请参阅 导入系统的文档

原文由 J.Baoby 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题