Мені потрібно знати, чи існує модуль 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 вчора звів мене з розуму
Після використання відповіді yarbelk я зробив це, оскільки не потрібно імпортувати ìmp
.
try:
__import__('imp').find_module('eggs')
# Make things with supposed existing module
except ImportError:
pass
Корисно, наприклад, у Джанго settings.py
.
Це 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
Виведе:
для "lkajshdflkahsodf" не знайдено документації Python "
і вихід.
Використовуйте одну з функцій pkgutil , наприклад:
from pkgutil import iter_modules
def module_exists(module_name):
return module_name in (name for loader, name, ispkg in iter_modules())
Простіше, якщо заява від 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
оскільки власне імпорт імпорту - просто ямл. Тож, поки ви знаєте, що ваш імпорт, це повинно зробити трюк для вас.
Я написав цю функцію помічника:
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
Немає можливості достовірно перевірити, чи "пунктирний модуль" імпортується, не імпортуючи його батьківський пакет. Кажучи це, існує багато рішень проблеми "як перевірити, чи існує модуль Python".
Нижче вирішується проблема, що імпортований модуль може підняти ImportError навіть якщо він існує. Ми хочемо відрізнити таку ситуацію від такої, в якій модуля не існує.
Пітон 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
Пітон 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