Мне нужно знать, существует ли модуль Python, не импортируя его.
Импортировать то, что может не существовать (не то, что я хочу):
try:
import eggs
except ImportError:
pass
Мне нужно знать, существует ли модуль Python, не импортируя его.
Импортировать то, что может не существовать (не то, что я хочу):
try:
import eggs
except ImportError:
pass
Ответы:
Чтобы проверить, может ли импорт найти что-то в 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
Вы должны использовать 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.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=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')
комментарии добро пожаловать на это
find_loader
eggs.ham.spam
.
spam
в eggs.ham
вы будете использоватьimp.find_module('spam', ['eggs', 'ham'])
pkgutil.find_loader("my.package.module")
возвращает загрузчик, если пакет / модуль существует, а None
если нет. Пожалуйста, обновите свой ответ для Python 2, так как маскировка ImportError свела меня с ума вчера xP
После использования ответа Ярбелк я сделал это, так как не нужно импортировать ìmp
.
try:
__import__('imp').find_module('eggs')
# Make things with supposed existing module
except ImportError:
pass
Полезно, settings.py
например, в Django .
Он 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
import pkgutil
import importlib
if pkgutil.find_loader(mod) is not None:
return importlib.import_module(mod)
return None
Многие ответы используют ловлю ImportError
. Проблема в том, что мы не можем знать, что бросает ImportError
.
Если вы импортируете свой существующий модуль и ImportError
в вашем модуле окажется (например, опечатка в строке 1), результатом будет то, что ваш модуль не существует. Для того, чтобы выяснить, что ваш модуль существует, ImportError
он пойман и заставляет вещи молча терпеть неудачу.
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
>>> 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
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
Будет вывод:
не найдена документация 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())
Упрощенный оператор if из AskUbuntu: как проверить, установлен ли модуль в Python?
import sys
print('eggs' in sys.modules)
Вы можете написать небольшой скрипт, который попытается импортировать все модули и сказать, какие из них работают с ошибками, а какие работают:
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. Так что, пока вы знаете свой импорт, это должно помочь вам.
Я написал эту вспомогательную функцию:
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
Вы также можете использовать importlib
напрямую
import importlib
try:
importlib.import_module(module_name)
except ImportError:
# Handle error
Невозможно надежно проверить, можно ли импортировать «пунктирный модуль» без импорта его родительского пакета. Сказав это, есть много решений проблемы "как проверить, существует ли модуль 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
в django.utils.module_loading.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