Как проверить, существует ли модуль python без его импорта



Мне нужно знать, существует ли модуль python, не импортируя его.



импортировать что-то, что может не существовать (не то, что я хочу):



try:
import eggs
except ImportError:
pass
575   11  

11 ответов:

вместо python2

чтобы проверить, если импорт может найти что-то в python2, используя 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 (более или менее то же самое, что и часть python3

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

Python3

Python3 ≤ 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)

Python3 ≥ 3.4

В Питон3.4 importlib.find_loaderpython 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

это также работает с относительным импортом, но вы должны поставить начало пакет, так что вы могли бы сделать:

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')

комментарии приветствуются о это

благодарности

  • @rvighne для importlib
  • @lucas-guido для python3. 3 + depricating find_loader
  • @enpenax для pkgutils.поведение find_loader в python2. 7

после использования ответа ярбелька, я сделал это для не нужно импортировать ìmp.

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

полезно в например.

ответ go_as как один лайнер

 python -c "help('modules');" | grep module

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.

если вы импортируете existant модуль и там оказывается ImportError в вашем модуле (например, опечатка в строке 1), результат будет пусть ваш модуль не существует. Это займет у вас довольно много времени, чтобы выяснить, что ваш модуль существует и ImportError пойман и делает вещи терпят неудачу молча.

использовать функции pkgutil, например:

from pkgutil import iter_modules

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

я столкнулся с этим вопросом при поиске способа проверить, загружен ли модуль из командная строка и хотел бы поделиться своими мыслями для тех, кто идет за мной и ищет то же самое:

Linux/UNIX script file method: файл module_help.py:

#!/usr/bin/env python

help('modules')

затем убедитесь, что это исполняемый файл:chmod u+x module_help.py

и назвать его с pipe до grep:

./module_help.py | grep module_name

вызвать система поможет. (Эта функция предназначен для интерактивного использования.) Если аргумент не задан, интерактивная справочная система запускается на консоли интерпретатора. Если аргумент строка, затем строка ищется как имя a модуль, функция, класс, метод, ключевое слово или раздел документации, и страница справки печатается на консоли. Если аргументом является любой другой вид объекта, то на странице справки объект создается.

интерактивный метод: в консоли нагрузка python

>>> help('module_name')

если найдено, прекратите чтение, набрав q
Для выхода из интерактивного сеанса python нажмите Ctrl + D

метод файла сценария Windows также совместим с Linux / UNIX,и лучше в целом:

#!/usr/bin/env python

import sys

help(sys.argv[1])

вызов его из команды, как:

python module_help.py site  

выводит:

справка на сайте модуль:

NAME сайт-добавление путей поиска модуля для сторонних пакетов в sys.путь.

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

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

DESCRIPTION
...
:

и вам придется нажать q для выхода интерактивный режим.

используя его неизвестный модуль:

python module_help.py lkajshdflkahsodf

выводит:

не найдено документации на Python для 'lkajshdflkahsodf'

и выход.

вы можете просто написать небольшой скрипт, который будет пытаться импортировать все модули и сказать вам, какие из них не работают и какие из них работают:

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 failed with error code: No module named pyyaml потому что фактическое имя импорта - это просто yaml. Так что пока вы знаете свой импорт, это должно сделать трюк для вас.

вы также можете использовать importlib напрямую

import importlib

try:
    importlib.import_module(module_name)
except ImportError:
    # Handle error

Python 3 > = 3.6: ModuleNotFoundError

The ModuleNotFoundError был введен в python 3.6 и может быть использован для этой цели

try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass

ошибка возникает при модуль или один из его родителей не может быть найден. Так что

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

будет печатать сообщение, которое выглядит как No module named 'eggs' Если eggs модуль не может быть найден; но напечатать что-то вроде No module named 'eggs.sub' если только sub модуль не мог а eggs пакет может быть найден.

посмотреть Документация системы импорта подробнее о ModuleNotFoundError

Python 2:

нет способа надежно проверить, можно ли импортировать "точечный модуль" без импорта его родительского пакета. Говоря это, есть много решений проблемы "как проверить, существует ли модуль Python".

ниже Решение проблемы, что импортированный модуль может вызвать ImportError даже он существует. Мы хотим отличить ту ситуацию от такой, в которой модуль не существует.

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

в Django.utils.загрузка модуля.module_has_submodule


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

Comments

    Ничего не найдено.