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

如何在不导入python模块的情况下检查python模块是否存在,python,python-import,Python,Python Import,我需要知道python模块是否存在,而不导入它 导入可能不存在的内容不是我想要的: try: import eggs except ImportError: pass 蟒蛇2 使用imp检查导入是否可以在python2中找到某些内容 要查找虚线导入,您需要执行更多操作: import imp try: spam_info = imp.find_module('spam') spam = imp.load_module('spam', *spam_info)

我需要知道python模块是否存在,而不导入它

导入可能不存在的内容不是我想要的:

try:
    import eggs
except ImportError:
    pass
蟒蛇2 使用imp检查导入是否可以在python2中找到某些内容

要查找虚线导入,您需要执行更多操作:

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_加载器,与python3部分大致相同

import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None
蟒蛇3 蟒蛇3≤ 3.3 您应该使用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)
from pkgutil import iter_modules

def module_exists(module_name):
    return module_name in (name for loader, name, ispkg in iter_modules())
蟒蛇3≥ 3.4 在Python3.4中,importlib.find_加载程序被弃用,取而代之的是importlib.util.find_规范。推荐的方法是importlib.util.find_规范。还有其他方法,如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.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')
欢迎对绕过此问题发表评论

致谢 @用于importlib的rvighne @lucas guido用于python3.3+去润滑查找加载器 @Pkthon2.7中pkgutils.find_加载程序行为的enpenax 使用以下选项之一,例如:

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)
from pkgutil import iter_modules

def module_exists(module_name):
    return module_name in (name for loader, name, ispkg in iter_modules())

在使用yarbelk的回复后,我为不必导入ìmp做了这个


例如,在Django的settings.py中很有用。

我在寻找检查模块是否从命令行加载的方法时遇到了这个问题,我想与大家分享我对后面的模块的看法,并寻找相同的模块:

Linux/UNIX脚本文件方法:生成文件模块\u help.py:

然后确保它是可执行的:chmodu+xmodule\u help.py

并用管道将其称为grep:

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

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

如果找到,请键入q退出阅读 要退出python交互式会话,请按Ctrl+D

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

从命令调用它,如:

python module_help.py site  
将输出:

模块站点上的帮助:

名字 站点-将第三方软件包的模块搜索路径附加到sys.path

文件 /usr/lib/python2.7/site.py

模块文档

描述 ... :

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

使用it未知模块:

python module_help.py lkajshdflkahsodf
将输出:

未找到“lkajshdflkahsodf”的Python文档


然后退出。

将as的答案作为一行

 python -c "help('modules');" | grep module
Python2,不依赖于恐怖 在更新当前答案之前,Python 2的方法如下

为什么还要另一个答案? 很多答案都是利用捕捉到一个重要的恐惧。问题是,我们不知道是什么引发了恐怖


如果您导入现有模块,并且模块中碰巧存在ImportError(例如第1行的输入错误),则结果将是您的模块不存在。您需要花费大量的回溯时间才能确定您的模块是否存在,并且ImportError被捕获并使事情无声地失败。

如果不导入其父包,则无法可靠地检查虚线模块是否可导入。尽管如此,对于如何检查Python模块是否存在的问题,有许多解决方案

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

Python 2:

导入导入库 进口蛋白胶 导入系统 def find_modulefull_module_名称: 如果可以导入模块“完整的模块名称”,则返回模块对象。 如果模块不存在,则返回None。 如果现有模块在导入期间引发异常,则引发异常。 模块=sys.modules.getfull\u模块\u名称 如果模块为无: module\u path\u tail=full\u module\u name.split'' 模块路径头=[] 加载器=真 当模块\路径\尾部和加载器: 模块路径头.appendmodule路径尾.pop0 模块名称=…连接模块路径头 loader=boolpkgutil.find\u loadermodule\u name 如果不是装载机: 仔细检查模块是否正确 现实并不存在 案例:完整模块名称=='paste.deploy' 尝试: importlib.import\u模块模块\u名称 除恐怖外: 通过 其他: 加载器=真 如果加载程序: module=importlib.import\u modulefull\u模块名称 返回模块 Python 3:

导入导入库 def find_modulefull_module_名称: 如果可以导入模块“完整的模块名称”,则返回模块对象。 如果模块不存在,则返回None。 如果现有模块在导入期间引发异常,则引发异常。 尝试: 返回importlib.import\u modulefull\u module\u名称 除exc外: 如果不是完整的“模块名称+”。请使用exc.name+”启动: 提升
在django.utils.module_加载中,module_有_子模块


import sys
import os
import imp

def module_has_submodule(package, module_name):
    """
    check module in package
    django.utils.module_loading.module_has_submodule
    """
    name = ".".join([package.__name__, module_name])
    try:
        # None indicates a cached miss; see mark_miss() in Python/import.c.
        return sys.modules[name] is not None
    except KeyError:
        pass
    try:
        package_path = package.__path__   # No __path__, then not a package.
    except AttributeError:
        # Since the remainder of this function assumes that we're dealing with
        # a package (module with a __path__), so if it's not, then bail here.
        return False
    for finder in sys.meta_path:
        if finder.find_module(name, package_path):
            return True
    for entry in package_path:
        try:
            # Try the cached finder.
            finder = sys.path_importer_cache[entry]
            if finder is None:
                # Implicit import machinery should be used.
                try:
                    file_, _, _ = imp.find_module(module_name, [entry])
                    if file_:
                        file_.close()
                    return True
                except ImportError:
                    continue
            # Else see if the finder knows of a loader.
            elif finder.find_module(name):
                return True
            else:
                continue
        except KeyError:
            # No cached finder, so try and make one.
            for hook in sys.path_hooks:
                try:
                    finder = hook(entry)
                    # XXX Could cache in sys.path_importer_cache
                    if finder.find_module(name):
                        return True
                    else:
                        # Once a finder is found, stop the search.
                        break
                except ImportError:
                    # Continue the search for a finder.
                    continue
            else:
                # No finder found.
                # Try the implicit import machinery if searching a directory.
                if os.path.isdir(entry):
                    try:
                        file_, _, _ = imp.find_module(module_name, [entry])
                        if file_:
                            file_.close()
                        return True
                    except ImportError:
                        pass
                # XXX Could insert None or NullImporter
    else:
        # Exhausted the search, so the module cannot be found.
        return False

您可以编写一个小脚本,尝试导入所有模块,并告诉您哪些模块出现故障,哪些模块正常工作:

import pip


if __name__ == '__main__':
    for package in pip.get_installed_distributions():
        pack_string = str(package).split(" ")[0]
        try:
            if __import__(pack_string.lower()):
                print(pack_string + " loaded successfully")
        except Exception as e:
            print(pack_string + " failed with error code: {}".format(e))
输出:

zope.interface loaded successfully
zope.deprecation loaded successfully
yarg loaded successfully
xlrd loaded successfully
WMI loaded successfully
Werkzeug loaded successfully
WebOb loaded successfully
virtualenv loaded successfully
...
警告:这将尝试导入所有内容,因此您将看到类似PyYAML失败的情况,错误代码为:没有名为PyYAML的模块,因为实际导入名称只是yaml。因此,只要您知道您的导入,这应该可以为您提供帮助。

您也可以直接使用importlib

import importlib

try:
    importlib.import_module(module_name)
except ImportError:
    # Handle error
Python 3>=3.6:ModuleNotFoundError Python3.6中引入了,可用于此目的

try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass
当找不到模块或其父模块之一时,将引发错误。所以

try:
    import eggs.sub
except ModuleNotFoundError as err:
    # Error handling
    print(err)
如果找不到鸡蛋模块,将打印一条看起来没有名为“鸡蛋”的模块的消息;但是如果只找到子模块而找不到eggs包,则会打印类似于没有名为“eggs.sub”的模块的内容


有关ModuleNotFoundError的更多信息,请参见AskUbuntu的一条更简单的if语句:


我编写了这个助手函数:

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


这只适用于顶级模块,不适用于eggs.ham.spam。@hemflit如果您想在eggs.ham中查找垃圾邮件,您可以使用imp.find_模块'spam',['egs',ham']+1,但在Python 3中,imp支持。如果导入的模块包含一个实际的ImportError,该怎么办。这就是发生在我身上的事。一年后,我遇到了上面提到的同样的问题,正在为Python 2寻找解决方案:pkgutil.find_loadermy.package.module如果包/模块存在,则返回一个加载器,如果不存在,则返回无。请更新您对Python2的回答,因为昨天屏蔽导入让我抓狂。我很好奇,使用导入有什么坏处?如果您的模块有副作用,调用导入可能会产生不必要的后果。因此,如果您想检查首先运行哪个版本的文件,您可以使用下面的答案进行检查,然后再进行导入。我并不是说写有副作用的模块是个好主意,但我们都是成年人,可以自己决定编写代码的危险程度。可能重复@ArtOfWarfare我刚刚结束了你链接的问题,作为这个问题的重复。因为这个问题更清楚,而且这里提出的解决方案比这里列出的所有其他解决方案都好。我宁愿让任何人知道这个更好的解决方案的答案,也不愿让人们远离它。@Chuck另外,模块可能存在,但本身可能包含导入错误。在上面的代码中捕获导入程序可能会导致指示模块不存在,而事实上它确实存在,但有错误。我投了反对票,因为这会掩盖模块中的导入错误,这使得很难发现错误。投反对票是个坏主意,好的做法是总是记录捕获的错误。这是一个在您编写所需内容后的示例。如果导入的模块在第1行出现ImportError失败,并且您的try-catch使其以静默方式失败,您将如何记录错误?我刚刚在现实生活中遇到了屏蔽导入错误问题,这是一个很糟糕的问题,导致了本应通过的测试!。我遇到有人用这个错误在另一个模块上触发monkeypatch。。。findIt可能不清楚,但除了第一个代码块之外,其他所有代码块都不依赖ImportError-如果您不清楚,请进行编辑。我看到您在前两个Python 2示例中使用了ImportError捕获。那么,它们为什么在那里呢?如果mod==“not_existing_package.mymodule”,这会引发严重的恐惧。看到我的全部,当然它抛出了一个导入错误。如果模块不存在,则应该抛出导入错误。这样你可以在需要的时候抓住它。其他解决方案的问题在于它们掩盖了其他错误。Try/except并不意味着你不能记录或确保事情的正确性。您可以完全捕获任何底层回溯,并对其执行任何操作。这只测试它是否已安装,而不是是否可安装。实际上,它测试它是否已导入,与所问的问题完全相反。问题是如何检查python模块是否存在
不导入它。不询问模块是否可安装?这有实际导入模块的问题。副作用和所有这些都满足了我在编程python时的标准问题:WWDD Django会做什么?我应该看一下,这并不能回答这个问题,因为如果它存在,它会导入包。如果另一个模块在导入过程中引发此异常,您将很难区分差异——您的模块是否不存在,或者它的某些依赖项是否不存在。
zope.interface loaded successfully
zope.deprecation loaded successfully
yarg loaded successfully
xlrd loaded successfully
WMI loaded successfully
Werkzeug loaded successfully
WebOb loaded successfully
virtualenv loaded successfully
...
import importlib

try:
    importlib.import_module(module_name)
except ImportError:
    # Handle error
try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass
try:
    import eggs.sub
except ModuleNotFoundError as err:
    # Error handling
    print(err)
import sys
print('eggs' in sys.modules)
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