我如何知道Python模块是否存在,而不导入它?

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

try:
    import eggs
except ImportError:
    pass

当前回答

没有任何方法可以在不导入其父包的情况下可靠地检查“虚线模块”是否可导入。说到这里,对于“如何检查Python模块是否存在”这个问题,有很多解决方案。

下面的解决方案解决了导入的模块即使存在也会引发ImportError的问题。我们希望将这种情况与模块不存在的情况区分开来。

Python 2:

import importlib
import pkgutil
import sys

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported.

    Returns None if module does not exist.

    Exception is raised if (existing) module raises exception during its import.
    """
    module = sys.modules.get(full_module_name)
    if module is None:
        module_path_tail = full_module_name.split('.')
        module_path_head = []
        loader = True
        while module_path_tail and loader:
            module_path_head.append(module_path_tail.pop(0))
            module_name = ".".join(module_path_head)
            loader = bool(pkgutil.find_loader(module_name))
            if not loader:
                # Double check if module realy does not exist
                # (case: full_module_name == 'paste.deploy')
                try:
                    importlib.import_module(module_name)
                except ImportError:
                    pass
                else:
                    loader = True
        if loader:
            module = importlib.import_module(full_module_name)
    return module

Python 3:

import importlib

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported.

    Returns None if module does not exist.

    Exception is raised if (existing) module raises exception during its import.
    """
    try:
        return importlib.import_module(full_module_name)
    except ImportError as exc:
        if not (full_module_name + '.').startswith(exc.name + '.'):
            raise

其他回答

没有任何方法可以在不导入其父包的情况下可靠地检查“虚线模块”是否可导入。说到这里,对于“如何检查Python模块是否存在”这个问题,有很多解决方案。

下面的解决方案解决了导入的模块即使存在也会引发ImportError的问题。我们希望将这种情况与模块不存在的情况区分开来。

Python 2:

import importlib
import pkgutil
import sys

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported.

    Returns None if module does not exist.

    Exception is raised if (existing) module raises exception during its import.
    """
    module = sys.modules.get(full_module_name)
    if module is None:
        module_path_tail = full_module_name.split('.')
        module_path_head = []
        loader = True
        while module_path_tail and loader:
            module_path_head.append(module_path_tail.pop(0))
            module_name = ".".join(module_path_head)
            loader = bool(pkgutil.find_loader(module_name))
            if not loader:
                # Double check if module realy does not exist
                # (case: full_module_name == 'paste.deploy')
                try:
                    importlib.import_module(module_name)
                except ImportError:
                    pass
                else:
                    loader = True
        if loader:
            module = importlib.import_module(full_module_name)
    return module

Python 3:

import importlib

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported.

    Returns None if module does not exist.

    Exception is raised if (existing) module raises exception during its import.
    """
    try:
        return importlib.import_module(full_module_name)
    except ImportError as exc:
        if not (full_module_name + '.').startswith(exc.name + '.'):
            raise

下面是一种检查模块是否从命令行加载的方法:

Linux/UNIX脚本文件方法:制作文件module_help.py:

#!/usr/bin/env python

help('modules')

然后确保它是可执行的:chmod u+x module_help.py

并使用管道调用grep:

./module_help.py | grep module_name

调用内置帮助系统。(此函数用于交互使用。)如果没有给出参数,交互式帮助系统将在解释器控制台上启动。如果参数是字符串,则该字符串将被查询为模块、函数、类、方法、关键字或文档主题的名称,并在控制台上打印帮助页面。如果参数是任何其他类型的对象,则生成该对象的帮助页面。

交互方法:在控制台中,加载python

>>> help('module_name')

如果发现,输入q停止读取。 按Ctrl + D退出Python解释器交互会话

Windows脚本文件方法,也兼容Linux/UNIX,整体上更好:

#!/usr/bin/env python

import sys

help(sys.argv[1])

从命令调用它,像这样:

python module_help.py site

将输出:

模块网站帮助: 的名字 site -将第三方包的模块搜索路径附加到sys.path。 文件 /usr/lib/python2.7/site.py 模块文档 http://docs.python.org/library/site 描述 ... :

你必须按q键才能退出交互模式。

将它用于未知模块,例如,

python module_help.py lkajshdflkahsodf

将输出:

没有找到'lkajshdflkahsodf'的Python文档

并退出。

在使用yarbelk的响应后,我做了这个,所以我不需要导入ìmp。

try:
    __import__('imp').find_module('eggs')
    # Make things with a supposed existing module
except ImportError:
    pass

例如,它在Django的settings.py文件中就很有用。

我写了这个helper函数:

def is_module_available(module_name):
    if sys.version_info < (3, 0):
        # python 2
        import importlib
        torch_loader = importlib.find_loader(module_name)
    elif sys.version_info <= (3, 3):
        # python 3.0 to 3.3
        import pkgutil
        torch_loader = pkgutil.find_loader(module_name)
    elif sys.version_info >= (3, 4):
        # python 3.4 and above
        import importlib
        torch_loader = importlib.util.find_spec(module_name)

    return torch_loader is not None

Python 2,不依赖于ImportError

在当前答案更新之前,以下是Python 2的方法

import pkgutil
import importlib

if pkgutil.find_loader(mod) is not None:
    return importlib.import_module(mod)
return None

为什么又是另一个答案?

很多答案都利用了捕捉ImportError。问题是,我们不知道是什么引发了ImportError。

如果你导入了你现有的模块,而你的模块中恰好有一个ImportError(例如,第1行有错字),结果将是你的模块不存在。

这将花费您大量的回溯来确定您的模块是否存在,ImportError被捕获并使事情无声地失败。