Как проверить, существует ли модуль python, не импортируя его
Мне нужно знать, существует ли модуль python, не импортируя его.
Импортировать что-то, что может не существовать (не то, что я хочу):
try: import eggs except ImportError: pass
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
В Python3.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.find_spec("food.eggs") module food loaded ModuleSpec(name='food.eggs', loader=, origin='/home/user/food/eggs.py')
комментарии приветствуются, обойдя это
Подтверждения
- @rvighne для importlib
- @lucas-guido для python3. 3+ лишает find_loader
- @enpenax для поведения pkgutils.find_loader в python2.7
После использования ответа yarbelk, я сделал это для не нужно импортировать ìmp .
try: __import__('imp').find_module('eggs') # Make things with supposed existing module except ImportError: pass
Полезно в Django settings.py например.
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 поймано и делает вещи терпимыми неудачно.
go_as ответ как один вкладыш
python -c "help('modules');" | grep module
Я наткнулся на этот вопрос, когда искал способ проверить, загружен ли модуль из командной строки , и хотел бы поделиться своими мыслями о тех, кто придет за мной и ищет то же самое:
Метод файла сценария Linux/UNIX: создать файл module_help.py :
#!/usr/bin/env python help('modules')
Затем убедитесь, что он исполняемый: chmod u+x module_help.py
И назовите его с pipe на grep :
./module_help.py | grep module_name
Вызвать встроенную справочную систему. (Эта функция предназначена для интерактивного использования.) Если аргумент не задан, интерактивная справочная система запускается на консоли переводчика. Если аргумент представляет собой строку, то строка ищется как имя модуля, функции, класса, метода, ключевого слова или раздела документации, и печатается страница справки. на консоли. Если в качестве аргумента используется объект любого другого типа, создается страница справки об этом объекте.
Интерактивный метод: в консоль загружают python
Если найдено, прекратите чтение, набрав q
Чтобы выйти из интерактивного сеанса Python, нажмите Ctrl + D
Метод файла сценария Windows также совместим с Linux/UNIX, и в целом лучше:
#!/usr/bin/env python import sys help(sys.argv[1])
Вызов из команды, например:
python module_help.py site
Помощь по модулю сайта:
NAME site – Добавьте пути поиска модулей для сторонних пакетов в sys.path.
FILE /usr/lib/python2.7/site.py
MODULE DOCS
http://docs.python.org/library/siteDESCRIPTION
…
:
и вам придется нажать q , чтобы выйти из интерактивного режима.
Используется неизвестный модуль:
python module_help.py lkajshdflkahsodf
документация Python для ‘lkajshdflkahsodf’ не найдена
Используйте одну из функций из pkgutil, например:
from pkgutil import iter_modules def module_exists(module_name): return module_name in (name for loader, name, ispkg in iter_modules())
Вы можете просто написать небольшую script, которая попыталась бы импортировать все модули и сказать, какие из них неисправны и какие из них работают:
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. Так что, пока вы знаете свой импорт, это должно сделать трюк для вас.
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)
будет печатать сообщение, которое выглядит как ” No module named ‘eggs’ если модуль eggs не может быть найден; но напечатал бы что-то вроде No module named ‘eggs.sub’ если бы не был найден только sub модуль, но пакет eggs можно было найти.
Дополнительную информацию о ModuleNotFoundError см. В документации системы импорта.
import sys print('eggs' in sys.modules)
Вы также можете напрямую использовать importlib
import importlib try: importlib.import_module(module_name) except ImportError: # Handle error
Невозможно надежно проверить, является ли “точечный модуль” доступным без импорта родительского пакета. Говоря об этом, существует множество решений проблемы “как проверить, существует ли модуль 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
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
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 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
Я написал эту вспомогательную функцию:
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, 4): # python 3.4 and above import importlib torch_loader = importlib.util.find_spec(module_name) return torch_loader is not None
Как проверить, был ли импортирован модуль python?
Причина, по которой я хочу проверить, уже ли я импортировал модуль, потому что у меня есть модуль, который я не хочу импортировать, потому что иногда это испортит мою программу.
Просто поместите raise SystemError() (или другое исключение по вашему выбору) вверху модуля, который вы не хотите импортировать. Если вы на самом деле импортировать его где - нибудь, ваша программа будет бросать отслеживающий и выход.
3 ответа
import sys modulename = 'datetime' if modulename not in sys.modules: print 'You have not imported the <> module'.format(modulename)
Это словарь, который отображает имена модулей в уже загруженные модули.
@VigneshKalai: это предложение не разбирается, извините. sys.modules содержит все модули, используемые в любом месте текущего экземпляра интерпретатора . Если datetime используется в любом другом модуле Python, он появится там.
@VigneshKalai . и datetime был просто примером модуля, вы бы заменили его на название модуля, которого боитесь.
@VigneshKalai: я использовал datetime в качестве примера, потому что вам, очевидно, нужно импортировать sys , чтобы иметь доступ к словарю sys.modules , а sys является скомпилированным модулем; это всегда там (это перечислено в sys.builtin_module_names .
Лучшее объяснение на данный момент. Perfect и Python Creators прибили его. Каждый день я продолжаю любить язык все больше и больше, благодаря постоянно расширяющемуся сообществу. Вы никогда не будете чувствовать себя обделенным. Спасибо - Мартин Питерс
Привет, @MartijnPieters. Большое спасибо за ваш ответ. Но как узнать имя, которое импортировал модуль? Например, я использую import numpy as np , как проверить, доступен ли np ?
@user15964: user15964: почему вы думаете, что нужно? Он будет зарегистрирован как sys.modules['numpy'] независимо от имени, использованного в модуле, который его импортировал.
@user15964: user15964: если вы пишете модуль и используете import numpy as np , то это ваш собственный код, и вы уже знаете, что использовали имя np .