如何检查python模块是否存在而不导入它

yar*_*elk 152 python python-import

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

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

try:
    import eggs
except ImportError:
    pass
Run Code Online (Sandbox Code Playgroud)

yar*_*elk 179

Python2

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

import imp
try:
    imp.find_module('eggs')
    found = True
except ImportError:
    found = False
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

你也可以使用pkgutil.find_loader(或多或少与python3部分相同

import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None
Run Code Online (Sandbox Code Playgroud)

Python3

Python3≤3.3

您应该使用importlib,我是如何做到这一点的:

import importlib
spam_loader = importlib.find_loader('spam')
found = spam_loader is not None
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

Python3≥3.4

在Python3.4中,importlib.find_loader python docs被弃用了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
Run Code Online (Sandbox Code Playgroud)

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

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

虽然我确信这样做有理由 - 我不确定它会是什么.

警告

在尝试查找子模块时,它将导入父模块(对于所有上述方法)!

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')
Run Code Online (Sandbox Code Playgroud)

欢迎回答这个问题

致谢

  • @rvighne for importlib
  • @ lucas-guido for python3.3 + depricating find_loader
  • @enpenax用于python2.7中的pkgutils.find_loader行为

  • +1,但`imp`是[已弃用](https://docs.python.org/3/library/imp.html),支持[`importlib`](https://docs.python.org/3 /library/importlib.html)在Python 3中. (5认同)
  • 如果导入的模块包含实际的"ImportError",该怎么办?这就是发生在我身上的事情.然后模块存在但不会"找到". (4认同)
  • 这仅适用于顶级模块,而不适用于`eggs.ham.spam`. (2认同)
  • @hemflit如果你想在`eggs.ham`中找到`spam`你会使用`imp.find_module('spam',['eggs','ham']) (2认同)
  • 如果您收到“importlib”没有“util”属性的错误,您可以按照[此答案](/sf/answers/2776278151/)进行修复。 (2认同)

J.B*_*oby 29

Python 3 >= 3.6:ModuleNotFoundError

ModuleNotFoundError在已经出台的Python 3.6,并且可以用于此目的

try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass
Run Code Online (Sandbox Code Playgroud)

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

try:
    import eggs.sub
except ModuleNotFoundError as err:
    # Error handling
    print(err)
Run Code Online (Sandbox Code Playgroud)

No module named 'eggs'如果eggs找不到模块,将打印一条消息;但是会打印一些类似的东西,No module named 'eggs.sub'如果sub找不到模块但可以找到eggs包。

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

  • 这并不能回答问题,因为它会导入包(如果存在) (9认同)
  • 如果另一个模块在导入期间引发此异常,您将无法(轻松)分辨出差异 - 您的模块是否不存在,或者它的某些依赖项是否不存在。 (2认同)

Zul*_*ulu 13

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

try:
    __import__('imp').find_module('eggs')
    # Make things with supposed existing module
except ImportError:
    pass
Run Code Online (Sandbox Code Playgroud)

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

  • 我downvoted,因为这掩盖了模块中的导入错误,这使得很难发现错误. (3认同)
  • 如果导入的模块在第1行出现ImportError失败,并且您的try catch使它静默失败,那么您将如何记录错误? (2认同)

enp*_*nax 11

Python 2,不依赖于ImportError

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

import pkgutil
import importlib

if pkgutil.find_loader(mod) is not None:
    return importlib.import_module(mod)
return None
Run Code Online (Sandbox Code Playgroud)

为什么另一个答案

许多答案都利用了捕捉ImportError.问题是,我们无法知道是什么抛出了ImportError.

如果您导入了existant模块并且模块中恰好有一个ImportError(例如第1行的拼写错误),结果将是您的模块不存在.它将花费你相当多的回溯来确定你的模块是否存在并且ImportError被捕获并使事情无声地失败.

  • 如果mod =='not_existing_package.mymodule',则抛出ImportError.请参阅我的完整[下面的解决方案](http://stackoverflow.com/a/35037157/1763149) (3认同)

小智 8

go_as作为一个班轮的答案

 python -c "help('modules');" | grep module
Run Code Online (Sandbox Code Playgroud)


go_*_*_as 6

我在寻找一种方法来检查一个模块是否从命令行加载 并且想要分享我对那些追随我的想法并寻找相同的方法时遇到了这个问题:

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

#!/usr/bin/env python

help('modules')
Run Code Online (Sandbox Code Playgroud)

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

并用a pipe来调用它grep:

./module_help.py | grep module_name
Run Code Online (Sandbox Code Playgroud)

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

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

>>> help('module_name')
Run Code Online (Sandbox Code Playgroud)

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

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

#!/usr/bin/env python

import sys

help(sys.argv[1])
Run Code Online (Sandbox Code Playgroud)

从命令调用它,如:

python module_help.py site  
Run Code Online (Sandbox Code Playgroud)

输出:

模块站点帮助:

NAME site - 将第三方软件包的模块搜索路径附加到sys.path.

FILE /usr/lib/python2.7/site.py

MODULE DOCS http://docs.python.org/library/site

DESCRIPTION
......
:

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

使用它未知模块:

python module_help.py lkajshdflkahsodf
Run Code Online (Sandbox Code Playgroud)

输出:

没有找到'lkajshdflkahsodf'的Python文档

并退出.


Art*_*are 5

使用pkgutil中的一个函数,例如:

from pkgutil import iter_modules

def module_exists(module_name):
    return module_name in (name for loader, name, ispkg in iter_modules())
Run Code Online (Sandbox Code Playgroud)


Far*_*din 5

我写了这个辅助函数:

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
Run Code Online (Sandbox Code Playgroud)