Сообщить об ошибке.

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

В этом разделе показаны практические приемы работы с пакетом importlib.

Содержание:


Импортировать программно:

Чтобы программно импортировать модуль, используйте importlib.import_module().

import importlib

itertools = importlib.import_module('itertools')

Проверка возможности импорта модуля:

Если вам нужно выяснить, можно ли импортировать модуль без фактического импорта, вам следует использовать importlib.util.find_spec ().

import importlib.util
import sys

# чисто для иллюстрации
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # Если надо выполнить фактический импорт ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

Импорт исходного файла напрямую:

Чтобы импортировать исходный файл Python напрямую, используйте следующий рецепт (только Python 3.5 и новее):

import importlib.util
import sys

# чисто для иллюстрации
import tokenize
file_path = tokenize.__file__
module_name = tokenize.__name__

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

Настройка импортера:

Для глубокой настройки импорта обычно требуется реализовать импортер. Это означает, что нужно управлять как поиском, так и загрузчиком. Для поиска есть два варианта на выбор в зависимости от ваших потребностей: поиск мета-пути или поиск пути. Первый - это то, что вы бы поместили в sys.meta_path, а второй - то, что вы создаете, используя хук записи пути к sys.path_hooks, который работает с записями sys.path.

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

import importlib.machinery
import sys

# чисто для иллюстрации
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
                  importlib.machinery.SOURCE_SUFFIXES)

# Настройка мета пути поиска.
# необходимо поместить искатель в нужное 
# место в списке с точки зрения приоритета.
sys.meta_path.append(SpamMetaPathFinder)

# Настройка поиска пути.
# Нужно убедиться в том, что путь перехвачен в 
# правильном месте в списке, с точки зрения приоритета.
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

Приблизительная реализация importlib.import_module():

Ниже представлена приблизительная реализация функции importlib.import_module(). Этот код помогает проиллюстрировать различные API, которые предоставляет пакет importlib.

import importlib.util
import sys

def import_module(name, package=None):
    """An approximate implementation of import."""
    absolute_name = importlib.util.resolve_name(name, package)
    try:
        return sys.modules[absolute_name]
    except KeyError:
        pass

    path = None
    if '.' in absolute_name:
        parent_name, _, child_name = absolute_name.rpartition('.')
        parent_module = import_module(parent_name)
        path = parent_module.__spec__.submodule_search_locations
    for finder in sys.meta_path:
        spec = finder.find_spec(absolute_name, path)
        if spec is not None:
            break
    else:
        msg = f'No module named {absolute_name!r}'
        raise ModuleNotFoundError(msg, name=absolute_name)
    module = importlib.util.module_from_spec(spec)
    sys.modules[absolute_name] = module
    spec.loader.exec_module(module)
    if path is not None:
        setattr(parent_module, child_name, module)
    return module