importlib — Реализация import

Added in version 3.1.

Источник: Lib/importlib/__init__.py


Введение

Назначение пакета importlib состоит из трех частей.

Один из них - предоставить реализацию оператора import (и, соответственно, функции __import__()) в исходном коде Python. Это обеспечит реализацию import, переносимую в любой интерпретатор Python. Кроме того, такая реализация проще для восприятия, чем реализация на языке программирования, отличном от Python.

Во-вторых, компоненты для реализации import раскрыты в этом пакете, что облегчает пользователям создание собственных пользовательских объектов (известных как importer) для участия в процессе импорта.

В-третьих, пакет содержит модули, раскрывающие дополнительную функциональность для управления аспектами пакетов Python:

  • importlib.metadata представляет доступ к метаданным из сторонних дистрибутивов.

  • importlib.resources предоставляет процедуры для доступа к некодовым «ресурсам» из пакетов Python.

См.также

Заявление import

Ссылка на язык для оператора import.

Packages specification

Оригинальная спецификация пакетов. Некоторые семантики изменились с момента написания этого документа (например, перенаправление на основе None в sys.modules).

Функция __import__()

Оператор import - это синтаксический сахар для этой функции.

Инициализация пути поиска модуля sys.path

Инициализация sys.path.

PEP 235

Импорт на платформы, нечувствительные к регистру

PEP 263

Определение кодировок исходного кода Python

PEP 302

Новые крючки для импорта

PEP 328

Импорт: Многострочный и абсолютный/относительный

PEP 366

Явный относительный импорт главного модуля

PEP 420

Неявные пакеты пространства имен

PEP 451

Тип ModuleSpec для системы импорта

PEP 488

Ликвидация файлов PYO

PEP 489

Многофазная инициализация модуля расширения

PEP 552

Детерминированные пики

PEP 3120

Использование UTF-8 в качестве кодировки источника по умолчанию

PEP 3147

Справочники репозиториев PYC

Функции

importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)

Реализация встроенной функции __import__().

Примечание

При программном импорте модулей вместо этой функции следует использовать import_module().

importlib.import_module(name, package=None)

Импортировать модуль. Аргумент name указывает, какой модуль импортировать в абсолютном или относительном выражении (например, либо pkg.mod, либо ..mod). Если имя указано в относительном выражении, то аргумент package должен быть установлен в имя пакета, который будет выступать в качестве якоря для разрешения имени пакета (например, import_module('..mod', 'pkg.subpkg') импортирует pkg.mod).

Функция import_module() действует как упрощающая обертка вокруг importlib.__import__(). Это означает, что вся семантика этой функции вытекает из importlib.__import__(). Самое важное различие между этими двумя функциями заключается в том, что import_module() возвращает указанный пакет или модуль (например, pkg.mod), а __import__() возвращает пакет или модуль верхнего уровня (например, pkg).

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

Изменено в версии 3.3: Родительские пакеты импортируются автоматически.

importlib.invalidate_caches()

Аннулирует внутренние кэши искателей, хранящиеся по адресу sys.meta_path. Если finder реализует invalidate_caches(), то будет вызвана эта функция для выполнения аннулирования. Эту функцию следует вызывать, если во время работы программы создаются/устанавливаются какие-либо модули, чтобы гарантировать, что все искатели заметят существование нового модуля.

Added in version 3.3.

Изменено в версии 3.10: Замечены пакеты пространства имен, созданные/установленные в другом месте sys.path после того, как одно и то же пространство имен уже было импортировано.

importlib.reload(module)

Перезагрузить ранее импортированный модуль. Аргумент должен быть объектом модуля, поэтому он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля с помощью внешнего редактора и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение - объект модуля (который может быть другим, если при повторном импорте в sys.modules будет помещен другой объект).

Когда выполняется reload():

  • Код модуля Python перекомпилируется и код на уровне модуля выполняется заново, определяя новый набор объектов, которые привязываются к именам в словаре модуля, повторно используя loader, которая первоначально загрузила модуль. Функция init модулей расширения второй раз не вызывается.

  • Как и все остальные объекты в Python, старые объекты восстанавливаются только после того, как количество их ссылок упадет до нуля.

  • Имена в пространстве имен модуля обновляются, чтобы указать на все новые или измененные объекты.

  • Другие ссылки на старые объекты (например, имена, внешние по отношению к модулю) не могут ссылаться на новые объекты и должны быть обновлены в каждом пространстве имен, где они встречаются, если это необходимо.

Есть и ряд других предостережений:

Когда модуль перезагружается, его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имен отменяют старые определения, так что это, как правило, не является проблемой. Если в новой версии модуля не определено имя, которое было определено в старой версии, старое определение сохраняется. Эта возможность может быть использована с пользой для модуля, если он поддерживает глобальную таблицу или кэш объектов - с помощью оператора try можно проверить наличие таблицы и при желании пропустить ее инициализацию:

try:
    cache
except NameError:
    cache = {}

Перезагружать встроенные или динамически загружаемые модули, как правило, не очень полезно. Не рекомендуется перезагружать sys, __main__, builtins и другие ключевые модули. Во многих случаях модули расширения не предназначены для инициализации более одного раза и при перезагрузке могут дать произвольный сбой.

Если модуль импортирует объекты из другого модуля с помощью fromimport …, вызов reload() для другого модуля не переопределяет импортированные из него объекты - один из способов обойти это заключается в повторном выполнении оператора from, другой - в использовании import и квалифицированных имен (module.name) вместо этого.

Если модуль инстанцирует экземпляры класса, перезагрузка модуля, определяющего класс, не влияет на определения методов экземпляров - они продолжают использовать старое определение класса. То же самое справедливо и для производных классов.

Added in version 3.4.

Изменено в версии 3.7: ModuleNotFoundError возникает, если в перезагружаемом модуле отсутствует ModuleSpec.

importlib.abc – Абстрактные базовые классы, связанные с импортом

Источник: Lib/importlib/abc.py


Модуль importlib.abc содержит все основные абстрактные базовые классы, используемые в import. Некоторые подклассы основных абстрактных базовых классов также предоставляются для помощи в реализации основных ABC.

Иерархия ABC:

object
 +-- MetaPathFinder
 +-- PathEntryFinder
 +-- Loader
      +-- ResourceLoader --------+
      +-- InspectLoader          |
           +-- ExecutionLoader --+
                                 +-- FileLoader
                                 +-- SourceLoader
class importlib.abc.MetaPathFinder

Абстрактный базовый класс, представляющий meta path finder.

Added in version 3.3.

Изменено в версии 3.10: Больше не является подклассом Finder.

find_spec(fullname, path, target=None)

Абстрактный метод для поиска spec для указанного модуля. Если это импорт верхнего уровня, то path будет значением None. В противном случае, это поиск подпакета или модуля, и path будет значением __path__ из родительского пакета. Если спецификация не найдена, возвращается None. При передаче target - это объект модуля, который может быть использован искателем для более точного определения того, какую спецификацию следует вернуть. importlib.util.spec_from_loader() может быть полезен для реализации конкретных MetaPathFinders.

Added in version 3.4.

invalidate_caches()

Необязательный метод, который при вызове должен аннулировать любой внутренний кэш, используемый искателем. Используется importlib.invalidate_caches() при аннулировании кэшей всех искателей на sys.meta_path.

Изменено в версии 3.4: Возвращает None при вызове вместо NotImplemented.

class importlib.abc.PathEntryFinder

Абстрактный базовый класс, представляющий path entry finder. Хотя он имеет некоторое сходство с MetaPathFinder, PathEntryFinder предназначен для использования только в рамках подсистемы импорта на основе путей, предоставляемой importlib.machinery.PathFinder.

Added in version 3.3.

Изменено в версии 3.10: Больше не является подклассом Finder.

find_spec(fullname, target=None)

Абстрактный метод для поиска spec для указанного модуля. Метод будет искать модуль только в пределах path entry, которому он назначен. Если модуль не найден, возвращается None. При передаче target - это объект модуля, который finder может использовать для более обоснованного предположения о том, какую спецификацию вернуть. importlib.util.spec_from_loader() может быть полезен для реализации конкретных PathEntryFinders.

Added in version 3.4.

invalidate_caches()

Необязательный метод, который при вызове должен аннулировать любой внутренний кэш, используемый искателем. Используется importlib.machinery.PathFinder.invalidate_caches() при аннулировании кэшей всех кэшированных искателей.

class importlib.abc.Loader

Абстрактный базовый класс для loader. Точное определение загрузчика см. в разделе PEP 302.

Загрузчики, которые хотят поддерживать чтение ресурсов, должны реализовать метод get_resource_reader(), как указано в importlib.resources.abc.ResourceReader.

Изменено в версии 3.7: Введен необязательный метод get_resource_reader().

create_module(spec)

Метод, возвращающий объект модуля, который следует использовать при импорте модуля. Этот метод может возвращать None, указывая на то, что должна использоваться семантика создания модуля по умолчанию.

Added in version 3.4.

Изменено в версии 3.6: Этот метод больше не является необязательным, если определена exec_module().

exec_module(module)

Абстрактный метод, который выполняет модуль в его собственном пространстве имен, когда модуль импортируется или перезагружается. При вызове exec_module() модуль уже должен быть инициализирован. Когда этот метод существует, должен быть определен create_module().

Added in version 3.4.

Изменено в версии 3.6: create_module() также должен быть определен.

load_module(fullname)

Унаследованный метод для загрузки модуля. Если модуль не может быть загружен, вызывается сообщение ImportError, в противном случае возвращается загруженный модуль.

Если запрашиваемый модуль уже существует в sys.modules, он должен быть использован и перезагружен. В противном случае загрузчик должен создать новый модуль и вставить его в sys.modules до начала загрузки, чтобы предотвратить рекурсию при импорте. Если загрузчик вставил модуль и загрузка не удалась, он должен удалить его из sys.modules; модули, уже находившиеся в sys.modules до начала выполнения загрузчика, должны быть оставлены в покое.

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

  • __name__

    Полное квалифицированное имя модуля. Для выполненного модуля оно равно '__main__'.

  • __file__

    Место, которое loader использовалось для загрузки модуля. Например, для модулей, загружаемых из файла .py, это имя файла. Устанавливается не для всех модулей (например, встроенных).

  • __cached__

    Имя файла скомпилированной версии кода модуля. Устанавливается не для всех модулей (например, встроенных).

  • __path__

    Список мест, где будут находиться подмодули пакета. Чаще всего это один каталог. Система импорта передает этот атрибут в __import__() и в finders так же, как и sys.path, но только для пакета. Он не устанавливается для непакетных модулей, поэтому его можно использовать как индикатор того, что модуль является пакетом.

  • __package__

    Полное имя пакета, в котором находится модуль (или пустая строка для модуля верхнего уровня). Если модуль является пакетом, то это то же самое, что и __name__.

  • __loader__

    Значение loader, используемое для загрузки модуля.

Если доступен exec_module(), то обеспечивается обратно совместимая функциональность.

Изменено в версии 3.4: Поднимайте ImportError при вызове вместо NotImplementedError. Функциональность предоставляется при наличии exec_module().

Не рекомендуется, начиная с версии 3.4: Рекомендуемый API для загрузки модуля - exec_module()create_module()). Загрузчики должны реализовывать его вместо load_module(). Механизм импорта берет на себя все остальные обязанности load_module(), когда реализуется exec_module().

class importlib.abc.ResourceLoader

Абстрактный базовый класс для loader, который реализует дополнительный протокол PEP 302 для загрузки произвольных ресурсов из внутреннего хранилища.

Не рекомендуется, начиная с версии 3.7: Этот ABC устарел в пользу поддержки загрузки ресурсов через importlib.resources.abc.ResourceReader.

abstractmethod get_data(path)

Абстрактный метод, возвращающий байты для данных, расположенных по адресу path. Загрузчики, имеющие файлоподобное хранилище, позволяющее хранить произвольные данные, могут реализовать этот абстрактный метод для прямого доступа к хранимым данным. Если путь не может быть найден, вызывается сообщение OSError. Ожидается, что путь будет создан с помощью атрибута __file__ модуля или элемента из __path__ пакета.

Изменено в версии 3.4: Поднимает OSError вместо NotImplementedError.

class importlib.abc.InspectLoader

Абстрактный базовый класс для loader, который реализует дополнительный протокол PEP 302 для загрузчиков, проверяющих модули.

get_code(fullname)

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

Примечание

Хотя метод имеет реализацию по умолчанию, рекомендуется переопределить его, если это возможно для повышения производительности.

Изменено в версии 3.4: Больше не является абстрактным и предоставляет конкретную реализацию.

abstractmethod get_source(fullname)

Абстрактный метод для возврата исходного текста модуля. Он возвращается в виде текстовой строки с использованием universal newlines, переводя все распознанные разделители строк в символы '\n'. Возвращает None, если источник недоступен (например, встроенный модуль). Возвращает ImportError, если загрузчик не может найти указанный модуль.

Изменено в версии 3.4: Поднимает ImportError вместо NotImplementedError.

is_package(fullname)

Необязательный метод, возвращающий значение true, если модуль является пакетом, и false в противном случае. Значение ImportError возвращается, если loader не может найти модуль.

Изменено в версии 3.4: Поднимает ImportError вместо NotImplementedError.

static source_to_code(data, path='<string>')

Создайте объект кода из источника Python.

Аргумент data может быть любым, который поддерживает функция compile() (например, строка или байт). Аргумент path должен быть «путем» к месту, откуда взят исходный код, который может быть абстрактным понятием (например, расположение в zip-файле).

С последующим кодовым объектом можно выполнить его в модуле, запустив exec(code, module.__dict__).

Added in version 3.4.

Изменено в версии 3.5: Сделал метод статическим.

exec_module(module)

Реализация Loader.exec_module().

Added in version 3.4.

load_module(fullname)

Реализация Loader.load_module().

Не рекомендуется, начиная с версии 3.4: используйте вместо этого exec_module().

class importlib.abc.ExecutionLoader

Абстрактный базовый класс, наследуемый от InspectLoader, который, будучи реализованным, помогает модулю выполняться как скрипт. ABC представляет необязательный протокол PEP 302.

abstractmethod get_filename(fullname)

Абстрактный метод, который должен возвращать значение __file__ для указанного модуля. Если путь недоступен, возвращается значение ImportError.

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

Изменено в версии 3.4: Поднимает ImportError вместо NotImplementedError.

class importlib.abc.FileLoader(fullname, path)

Абстрактный базовый класс, который наследуется от ResourceLoader и ExecutionLoader, предоставляя конкретные реализации ResourceLoader.get_data() и ExecutionLoader.get_filename().

Аргумент fullname - это полностью разрешенное имя модуля, с которым должен работать загрузчик. Аргумент path - это путь к файлу с модулем.

Added in version 3.3.

name

Имя модуля, с которым может работать загрузчик.

path

Путь к файлу модуля.

load_module(fullname)

Вызывает супер load_module().

Не рекомендуется, начиная с версии 3.4: Вместо этого используйте Loader.exec_module().

abstractmethod get_filename(fullname)

Возвращает path.

abstractmethod get_data(path)

Считывает path как двоичный файл и возвращает байты из него.

class importlib.abc.SourceLoader

Абстрактный базовый класс для реализации загрузки исходных файлов (и, опционально, байткода). Класс наследуется от ResourceLoader и ExecutionLoader, требуя реализации:

Абстрактные методы, определенные этим классом, предназначены для добавления необязательной поддержки файлов байткода. Если не реализовать эти необязательные методы (или заставить их вызывать NotImplementedError), загрузчик будет работать только с исходным кодом. Реализация этих методов позволяет загрузчику работать с файлами исходного кода и байткода; она не позволяет загружать без источника, где предоставляется только байткод. Файлы байткода - это оптимизация для ускорения загрузки за счет удаления этапа разбора компилятора Python, поэтому API, специфичный для байткода, не предоставляется.

path_stats(path)

Необязательный абстрактный метод, возвращающий dict, содержащий метаданные об указанном пути. Поддерживаются следующие ключи словаря:

  • 'mtime' (обязательно): целое число или число с плавающей точкой, представляющее время модификации исходного кода;

  • 'size' (необязательно): размер исходного кода в байтах.

Любые другие ключи в словаре игнорируются, чтобы обеспечить возможность будущих расширений. Если путь не может быть обработан, выдается сообщение OSError.

Added in version 3.3.

Изменено в версии 3.4: Поднимите OSError вместо NotImplementedError.

path_mtime(path)

Необязательный абстрактный метод, возвращающий время модификации для указанного пути.

Не рекомендуется, начиная с версии 3.3: Этот метод устарел в пользу path_stats(). Вы не обязаны его реализовывать, но он по-прежнему доступен для совместимости. Вызывает OSError, если путь не может быть обработан.

Изменено в версии 3.4: Поднимите OSError вместо NotImplementedError.

set_data(path, data)

Необязательный абстрактный метод, который записывает указанные байты в файл по пути. Все несуществующие промежуточные каталоги будут созданы автоматически.

Если запись в путь не удается, потому что путь доступен только для чтения (errno.EACCES/PermissionError), не распространяйте исключение.

Изменено в версии 3.4: Больше не поднимает NotImplementedError при вызове.

get_code(fullname)

Конкретная реализация InspectLoader.get_code().

exec_module(module)

Конкретная реализация Loader.exec_module().

Added in version 3.4.

load_module(fullname)

Конкретная реализация Loader.load_module().

Не рекомендуется, начиная с версии 3.4: Вместо этого используйте exec_module().

get_source(fullname)

Конкретная реализация InspectLoader.get_source().

is_package(fullname)

Конкретная реализация InspectLoader.is_package(). Модуль считается пакетом, если путь к его файлу (как указано в ExecutionLoader.get_filename()) представляет собой файл с именем __init__, если удалить расширение файла и само имя модуля не заканчивается на __init__.

class importlib.abc.ResourceReader

Заменено на TraversableResources.

Значение abstract base class, обеспечивающее возможность чтения ресурсов.

С точки зрения этого букваря, ресурс - это двоичный артефакт, который поставляется в составе пакета. Обычно это что-то вроде файла данных, который находится рядом с __init__.py файлом пакета. Цель этого класса - помочь абстрагироваться от доступа к таким файлам данных, чтобы не имело значения, хранится ли пакет и его файл(ы) данных в файле zip, а не в файловой системе.

Для любого из методов этого класса аргумент resource должен быть path-like object, который концептуально представляет собой просто имя файла. Это означает, что в аргумент resource не должны включаться пути к подкаталогам. Это происходит потому, что в качестве «каталога» выступает местоположение пакета, для которого предназначен считыватель. Отсюда метафора для каталогов и имен файлов - пакеты и ресурсы, соответственно. Именно поэтому ожидается, что экземпляры этого класса будут напрямую соотноситься с конкретным пакетом (вместо того, чтобы потенциально представлять несколько пакетов или модуль).

Загрузчики, которые хотят поддерживать чтение ресурсов, должны предоставлять метод get_resource_reader(fullname), который возвращает объект, реализующий интерфейс этого ABC. Если модуль, указанный в fullname, не является пакетом, этот метод должен возвращать None. Объект, совместимый с данным ABC, должен возвращаться только в том случае, если указанный модуль является пакетом.

Added in version 3.7.

Утратил актуальность с версии 3.12, удален в версии 3.14: Вместо этого используйте importlib.resources.abc.TraversableResources.

abstractmethod open_resource(resource)

Возвращает открытое значение, file-like object для бинарного чтения ресурса.

Если ресурс не может быть найден, выдается сообщение FileNotFoundError.

abstractmethod resource_path(resource)

Возвращает путь файловой системы к ресурсу.

Если ресурс конкретно не существует в файловой системе, поднимите FileNotFoundError.

abstractmethod is_resource(name)

Возвращает True, если имя name считается ресурсом. Возвращается FileNotFoundError, если имя name не существует.

abstractmethod contents()

Возвращает iterable строк над содержимым пакета. Обратите внимание, что не обязательно, чтобы все имена, возвращаемые итератором, были реальными ресурсами, например, допустимо возвращать имена, для которых is_resource() будет ложным.

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

Абстрактный метод возвращает итерабельную таблицу, не содержащую элементов.

class importlib.abc.Traversable

Объект с подмножеством методов pathlib.Path, подходящих для обхода каталогов и открытия файлов.

Для представления объекта в файловой системе используйте importlib.resources.as_file().

Added in version 3.9.

Утратил актуальность с версии 3.12, удален в версии 3.14: Вместо этого используйте importlib.resources.abc.Traversable.

name

Абстрактное. Базовое имя этого объекта без каких-либо родительских ссылок.

abstractmethod iterdir()

Добывайте Traversable объектов в self.

abstractmethod is_dir()

Верните True, если self является каталогом.

abstractmethod is_file()

Верните True, если self - это файл.

abstractmethod joinpath(child)

Возвращает обходной ребенок в self.

abstractmethod __truediv__(child)

Верните Traversable ребенка в self.

abstractmethod open(mode='r', *args, **kwargs)

mode может быть „r“ или „rb“ для открытия в текстовом или двоичном виде. Возвращает хэндл, пригодный для чтения (то же, что и pathlib.Path.open).

При открытии в виде текста принимает параметры кодировки, подобные тем, что принимает io.TextIOWrapper.

read_bytes()

Считывание содержимого self в виде байтов.

read_text(encoding=None)

Прочитайте содержимое self как текст.

class importlib.abc.TraversableResources

Абстрактный базовый класс для считывателей ресурсов, способных обслуживать интерфейс importlib.resources.files(). Является подклассом importlib.resources.abc.ResourceReader и предоставляет конкретные реализации абстрактных методов importlib.resources.abc.ResourceReader. Поэтому любой загрузчик, поставляющий importlib.abc.TraversableResources, также поставляет ResourceReader.

Загрузчики, которые хотят поддерживать чтение ресурсов, должны реализовать этот интерфейс.

Added in version 3.9.

Утратил актуальность с версии 3.12, удален в версии 3.14: Вместо этого используйте importlib.resources.abc.TraversableResources.

abstractmethod files()

Возвращает объект importlib.resources.abc.Traversable для загруженного пакета.

importlib.machinery – Импортеры и крючки путей

Источник: Lib/importlib/machinery.py


Этот модуль содержит различные объекты, которые помогают import находить и загружать модули.

importlib.machinery.SOURCE_SUFFIXES

Список строк, представляющих распознанные суффиксы файлов для исходных модулей.

Added in version 3.3.

importlib.machinery.DEBUG_BYTECODE_SUFFIXES

Список строк, представляющих суффиксы файлов для неоптимизированных модулей байткода.

Added in version 3.3.

Не рекомендуется, начиная с версии 3.5: Вместо этого используйте BYTECODE_SUFFIXES.

importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES

Список строк, представляющих суффиксы файлов для оптимизированных модулей байткода.

Added in version 3.3.

Не рекомендуется, начиная с версии 3.5: Вместо этого используйте BYTECODE_SUFFIXES.

importlib.machinery.BYTECODE_SUFFIXES

Список строк, представляющих распознанные суффиксы файлов для модулей байткода (включая ведущую точку).

Added in version 3.3.

Изменено в версии 3.5: Значение больше не зависит от __debug__.

importlib.machinery.EXTENSION_SUFFIXES

Список строк, представляющих распознанные суффиксы файлов для модулей расширения.

Added in version 3.3.

importlib.machinery.all_suffixes()

Возвращает объединенный список строк, представляющих все суффиксы файлов для модулей, распознаваемых стандартным механизмом импорта. Это помощник для кода, которому просто нужно знать, ссылается ли путь к файловой системе на модуль, не требуя подробностей о типе модуля (например, inspect.getmodulename()).

Added in version 3.3.

class importlib.machinery.BuiltinImporter

importer для встроенных модулей. Все известные встроенные модули перечислены в sys.builtin_module_names. Этот класс реализует importlib.abc.MetaPathFinder и importlib.abc.InspectLoader ABC.

В этом классе определяются только методы класса, чтобы избежать необходимости инстанцирования.

Изменено в версии 3.5: В рамках PEP 489 встроенный импортер теперь реализует Loader.create_module() и Loader.exec_module().

class importlib.machinery.FrozenImporter

Класс importer для замороженных модулей. Этот класс реализует importlib.abc.MetaPathFinder и importlib.abc.InspectLoader. ABC.

В этом классе определяются только методы класса, чтобы избежать необходимости инстанцирования.

Изменено в версии 3.4: Получил методы create_module() и exec_module().

class importlib.machinery.WindowsRegistryFinder

Finder для модулей, объявленных в реестре Windows. Этот класс реализует importlib.abc.MetaPathFinder ABC.

В этом классе определяются только методы класса, чтобы избежать необходимости инстанцирования.

Added in version 3.3.

Не рекомендуется, начиная с версии 3.6: Вместо этого используйте конфигурацию site. Будущие версии Python могут не включать этот поисковик по умолчанию.

class importlib.machinery.PathFinder

Класс Finder для атрибутов sys.path и пакета __path__. Этот класс реализует importlib.abc.MetaPathFinder ABC.

В этом классе определяются только методы класса, чтобы избежать необходимости инстанцирования.

classmethod find_spec(fullname, path=None, target=None)

Метод класса, который пытается найти spec для модуля, указанного fullname, в sys.path или, если определено, в path. Для каждого элемента пути, по которому ведется поиск, проверяется sys.path_importer_cache. Если найден объект, не являющийся ложным, то он используется в качестве path entry finder для поиска искомого модуля. Если запись в sys.path_importer_cache не найдена, то в sys.path_hooks ищется искатель для записи пути и, если он найден, сохраняется в sys.path_importer_cache вместе с запросом о модуле. Если искатель не найден, то None и сохраняется в кэше, и возвращается.

Added in version 3.4.

Изменено в версии 3.5: Если текущий рабочий каталог - представленный пустой строкой - больше не действителен, то возвращается None, но в sys.path_importer_cache значение не кэшируется.

classmethod invalidate_caches()

Вызывает importlib.abc.PathEntryFinder.invalidate_caches() для всех хранящихся в sys.path_importer_cache искателей, которые определяют метод. В противном случае записи в sys.path_importer_cache, установленные в None, удаляются.

Изменено в версии 3.7: Записи None в sys.path_importer_cache удаляются.

Изменено в версии 3.4: Вызывает объекты в sys.path_hooks с текущим рабочим каталогом для '' (т.е. пустой строкой).

class importlib.machinery.FileFinder(path, *loader_details)

Конкретная реализация importlib.abc.PathEntryFinder, которая кэширует результаты из файловой системы.

Аргумент path - это директория, в которой будет производиться поиск.

Аргумент loader_details представляет собой переменное количество кортежей из двух элементов, каждый из которых содержит загрузчик и последовательность суффиксов файлов, которые распознает загрузчик. Предполагается, что загрузчики являются вызываемыми файлами, которые принимают два аргумента: имя модуля и путь к найденному файлу.

Программа поиска будет кэшировать содержимое каталога по мере необходимости, выполняя вызовы stat при каждом поиске модуля, чтобы убедиться, что кэш не устарел. Поскольку устойчивость кэша зависит от детализации информации операционной системы о состоянии файловой системы, существует потенциальное состояние гонки: поиск модуля, создание нового файла, а затем поиск модуля, который представляет новый файл. Если эти операции выполняются достаточно быстро, чтобы уложиться в гранулярность вызовов stat, то поиск модуля завершится неудачей. Чтобы этого не произошло, при динамическом создании модуля обязательно вызывайте importlib.invalidate_caches().

Added in version 3.3.

path

Путь, по которому будет вестись поиск.

find_spec(fullname, target=None)

Попытка найти спецификацию для обработки fullname в пределах path.

Added in version 3.4.

invalidate_caches()

Очистите внутренний кэш.

classmethod path_hook(*loader_details)

Метод класса, который возвращает закрытие для использования на sys.path_hooks. Экземпляр FileFinder возвращается закрытием, используя аргумент path, переданный закрытию напрямую, и loader_details косвенно.

Если аргумент закрытия не является существующим каталогом, то будет поднят ImportError.

class importlib.machinery.SourceFileLoader(fullname, path)

Конкретная реализация importlib.abc.SourceLoader путем подклассификации importlib.abc.FileLoader и предоставления некоторых конкретных реализаций других методов.

Added in version 3.3.

name

Имя модуля, который будет обрабатывать этот загрузчик.

path

Путь к исходному файлу.

is_package(fullname)

Верните True, если path, по-видимому, относится к пакету.

path_stats(path)

Конкретная реализация importlib.abc.SourceLoader.path_stats().

set_data(path, data)

Конкретная реализация importlib.abc.SourceLoader.set_data().

load_module(name=None)

Конкретная реализация importlib.abc.Loader.load_module(), в которой указание имени загружаемого модуля необязательно.

Не рекомендуется, начиная с версии 3.6: Вместо этого используйте importlib.abc.Loader.exec_module().

class importlib.machinery.SourcelessFileLoader(fullname, path)

Конкретная реализация importlib.abc.FileLoader, которая может импортировать файлы байткода (т.е. файлы исходного кода отсутствуют).

Обратите внимание, что прямое использование файлов байткода (а не файлов исходного кода) препятствует использованию ваших модулей всеми реализациями Python или новыми версиями Python, изменяющими формат байткода.

Added in version 3.3.

name

Имя модуля, с которым будет работать загрузчик.

path

Путь к файлу байткода.

is_package(fullname)

Определяет, является ли модуль пакетом, на основании path.

get_code(fullname)

Возвращает объект кода для name, созданный из path.

get_source(fullname)

Возвращает None, так как файлы байткода не имеют источника при использовании этого загрузчика.

load_module(name=None)

Конкретная реализация importlib.abc.Loader.load_module(), в которой указание имени загружаемого модуля необязательно.

Не рекомендуется, начиная с версии 3.6: Вместо этого используйте importlib.abc.Loader.exec_module().

class importlib.machinery.ExtensionFileLoader(fullname, path)

Конкретная реализация importlib.abc.ExecutionLoader для модулей расширения.

Аргумент fullname указывает имя модуля, который должен поддерживать загрузчик. Аргумент path - это путь к файлу модуля расширения.

Обратите внимание, что по умолчанию импорт модуля расширения будет неудачным в субинтерпретаторах, если он не реализует многофазную инициализацию (см. PEP 489), даже если в противном случае импорт пройдет успешно.

Added in version 3.3.

Изменено в версии 3.12: Для использования в субинтерпретаторах теперь требуется многофазный init.

name

Имя модуля, который поддерживает загрузчик.

path

Путь к модулю расширения.

create_module(spec)

Создает объект модуля из заданной спецификации в соответствии с PEP 489.

Added in version 3.5.

exec_module(module)

Инициализирует заданный объект модуля в соответствии с PEP 489.

Added in version 3.5.

is_package(fullname)

Возвращает True, если путь к файлу указывает на модуль __init__ пакета, основанный на EXTENSION_SUFFIXES.

get_code(fullname)

Возвращает None, так как у модулей расширения отсутствует объект кода.

get_source(fullname)

Возвращает None, так как модули расширения не имеют исходного кода.

get_filename(fullname)

Возвращает path.

Added in version 3.4.

class importlib.machinery.NamespaceLoader(name, path, path_finder)

Конкретная реализация importlib.abc.InspectLoader для пакетов пространства имен. Это псевдоним для частного класса, который обнародуется только для интроспекции атрибута __loader__ для пакетов пространства имен:

>>> from importlib.machinery import NamespaceLoader
>>> import my_namespace
>>> isinstance(my_namespace.__loader__, NamespaceLoader)
True
>>> import importlib.abc
>>> isinstance(my_namespace.__loader__, importlib.abc.Loader)
True

Added in version 3.11.

class importlib.machinery.ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None)

Спецификация состояния модуля, связанного с системой импорта. Обычно отображается как атрибут __spec__ модуля. В описаниях ниже имена в круглых скобках указывают на соответствующий атрибут, доступный непосредственно на объекте модуля, например module.__spec__.origin == module.__file__. Заметим, однако, что хотя значения обычно эквивалентны, они могут отличаться, поскольку между двумя объектами нет синхронизации. Например, можно обновить __file__ модуля во время выполнения, и это не будет автоматически отражено в __spec__.origin модуля, и наоборот.

Added in version 3.4.

name

(__name__)

Полное имя модуля. В finder этот атрибут всегда должен быть установлен в непустую строку.

loader

(__loader__)

Атрибут loader, используемый для загрузки модуля. Атрибут finder должен быть установлен всегда.

origin

(__file__)

Место, которое loader должен использовать loader для загрузки модуля. Например, для модулей, загружаемых из файла .py, это имя файла. Атрибут finder должен всегда устанавливать это значение, чтобы loader мог его использовать. В редких случаях, когда такого значения нет (например, для пакетов пространства имен), оно должно быть установлено в None.

submodule_search_locations

(__path__)

Список мест, где будут находиться подмодули пакета. Чаще всего это один каталог. Атрибут finder должен устанавливать этот атрибут в список, даже пустой, чтобы указать системе импорта, что модуль является пакетом. Для непакетных модулей он должен быть установлен в None. Позже он автоматически устанавливается в специальный объект для пакетов пространства имен.

loader_state

Атрибут finder может быть установлен в объект, содержащий дополнительные, специфические для модуля данные, которые будут использоваться при загрузке модуля. В противном случае он должен быть установлен в None.

cached

(__cached__)

Имя файла скомпилированной версии кода модуля. Этот атрибут всегда должен быть установлен finder, но может быть None для модулей, которым не нужно хранить скомпилированный код.

parent

(__package__)

(Только для чтения) Полное имя пакета, в котором находится модуль (или пустая строка для модуля верхнего уровня). Если модуль является пакетом, то это то же самое, что и name.

has_location
True, если значение origin в спецификации относится к загружаемому месту,

False в противном случае. Это значение влияет на то, как интерпретируется origin и как заполняется __file__ модуля.

class importlib.machinery.AppleFrameworkLoader(name, path)

Специализация importlib.machinery.ExtensionFileLoader, способная загружать модули расширения в формате Framework.

Для совместимости с iOS App Store все двоичные модули в приложении для iOS должны быть динамическими библиотеками, содержащимися во фреймворке с соответствующими метаданными, который хранится в папке Frameworks упакованного приложения. Для каждого фреймворка может быть только один двоичный файл, и не может быть исполняемого двоичного материала вне папки Frameworks.

Чтобы удовлетворить это требование, при работе на iOS двоичные файлы модулей расширения не упаковываются как файлы .so на sys.path, а как отдельные автономные фреймворки. Чтобы обнаружить эти фреймворки, данный загрузчик регистрируется в расширении .fwork, а файл .fwork выступает в качестве держателя исходного местоположения бинарного файла на sys.path. Файл .fwork содержит путь к реальному двоичному файлу в папке Frameworks относительно пакета приложений. Чтобы разрешить возврат бинарных файлов, упакованных фреймворком, в исходное местоположение, фреймворк должен содержать файл .origin, который содержит местоположение файла .fwork относительно пакета приложений.

Например, рассмотрим случай импорта from foo.bar import _whiz, где _whiz реализован с помощью бинарного модуля sources/foo/bar/_whiz.abi3.so, причем sources - это место, зарегистрированное в sys.path, относительно пакета приложения. Этот модуль должен распространяться как Frameworks/foo.bar._whiz.framework/foo.bar._whiz (создавая имя фреймворка из полного пути импорта модуля), с файлом Info.plist в каталоге .framework, идентифицирующим бинарник как фреймворк. Модуль foo.bar._whiz будет представлен в исходном расположении с помощью файла-маркера sources/foo/bar/_whiz.abi3.fwork, содержащего путь Frameworks/foo.bar._whiz/foo.bar._whiz. Фреймворк также будет содержать Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin, содержащий путь к файлу .fwork.

Когда модуль загружается с помощью этого загрузчика, __file__ модуля будет отображаться как расположение .fwork файла. Это позволяет коду использовать __file__ модуля в качестве привязки для обхода файловой системы. Однако спецификация будет ссылаться на расположение фактического бинарного файла в папке .framework.

Проект Xcode, собирающий приложение, отвечает за преобразование любых файлов .so из папки PYTHONPATH в папку Frameworks (включая удаление расширений из файла модуля, добавление метаданных фреймворка и подписание полученного фреймворка), а также за создание файлов .fwork и .origin. Обычно это делается с помощью шага сборки в проекте Xcode; подробности о том, как создать этот шаг сборки, см. в документации по iOS.

Added in version 3.13.

Availability: iOS.

name

Имя модуля, который поддерживает загрузчик.

path

Путь к .fwork файлу для модуля расширения.

importlib.util – Код утилиты для импортеров

Источник: Lib/importlib/util.py


Этот модуль содержит различные объекты, которые помогают в построении importer.

importlib.util.MAGIC_NUMBER

Байт, представляющий номер версии байткода. Если вам нужна помощь в загрузке/записи байткода, рассмотрите вариант importlib.abc.SourceLoader.

Added in version 3.4.

importlib.util.cache_from_source(path, debug_override=None, *, optimization=None)

Возвращает путь PEP 3147/PEP 488 к байт-компилированному файлу, связанному с источником path. Например, если path - это /foo/bar/baz.py, то для Python 3.2 возвращаемое значение будет /foo/bar/__pycache__/baz.cpython-32.pyc. Строка cpython-32 берется из текущего магического тега (см. get_tag(); если sys.implementation.cache_tag не определен, то будет задан NotImplementedError).

Параметр оптимизация используется для указания уровня оптимизации файла байткода. Пустая строка означает отсутствие оптимизации, поэтому /foo/bar/baz.py с оптимизацией, равной '', приведет к пути к байткоду, равному /foo/bar/__pycache__/baz.cpython-32.pyc. None приводит к использованию уровня оптимизации интерпретатора. Любое другое значение используется в строковом представлении, поэтому /foo/bar/baz.py с оптимизацией 2 приведет к пути байткода /foo/bar/__pycache__/baz.cpython-32.opt-2.pyc. Строковое представление оптимизации может быть только буквенно-цифровым, в противном случае будет выдано сообщение ValueError.

Параметр debug_override является устаревшим и может быть использован для переопределения значения __debug__, установленного системой. Значение True эквивалентно установке оптимизации в пустую строку. Значение False равнозначно установке оптимизации в 1. Если оба значения debug_override и optimization не равны None, то возникает ошибка TypeError.

Added in version 3.4.

Изменено в версии 3.5: Был добавлен параметр optimization, а параметр debug_override был устаревшим.

Изменено в версии 3.6: Принимает path-like object.

importlib.util.source_from_cache(path)

Если задан путь к имени файла PEP 3147, то возвращается путь к соответствующему файлу исходного кода. Например, если path - это /foo/bar/__pycache__/baz.cpython-32.pyc, то возвращаемый путь будет /foo/bar/baz.py. Путь path не обязательно должен существовать, однако если он не соответствует формату PEP 3147 или PEP 488, возникает ошибка ValueError. Если sys.implementation.cache_tag не определен, возникает ошибка NotImplementedError.

Added in version 3.4.

Изменено в версии 3.6: Принимает path-like object.

importlib.util.decode_source(source_bytes)

Декодирует заданные байты, представляющие исходный код, и возвращает их в виде строки с универсальными новыми строками (как того требует importlib.abc.InspectLoader.get_source()).

Added in version 3.4.

importlib.util.resolve_name(name, package)

Преобразование относительного имени модуля в абсолютное.

Если name не содержит ведущих точек, то просто возвращается name. Это позволяет использовать, например, importlib.util.resolve_name('sys', __spec__.parent), не проверяя, нужен ли аргумент package.

ImportError возникает, если name - относительное имя модуля, а package - ложное значение (например, None или пустая строка). ImportError также будет поднята, если относительное имя будет исключать содержащий его пакет (например, запрос ..bacon из пакета spam).

Added in version 3.3.

Изменено в версии 3.9: Чтобы улучшить согласованность с заявлениями об импорте, поднимайте ImportError вместо ValueError для недопустимых попыток относительного импорта.

importlib.util.find_spec(name, package=None)

Находит spec для модуля, опционально относительно указанного имени package. Если модуль находится в sys.modules, то возвращается sys.modules[name].__spec__ (если только спецификация не будет None или не задана, в этом случае возвращается ValueError). В противном случае выполняется поиск с использованием sys.meta_path. Если спецификация не найдена, возвращается None.

Если name относится к подмодулю (содержит точку), то родительский модуль импортируется автоматически.

name и package работают так же, как и для import_module().

Added in version 3.4.

Изменено в версии 3.7: Вызывает ModuleNotFoundError вместо AttributeError, если package на самом деле не является пакетом (т.е. не имеет атрибута __path__).

importlib.util.module_from_spec(spec)

Создайте новый модуль на основе spec и spec.loader.create_module.

Если spec.loader.create_module не возвращает None, то все ранее существовавшие атрибуты не будут сброшены. Также не будет вызвано AttributeError, если оно сработает при обращении к spec или установке атрибута модуля.

Эта функция предпочтительнее, чем использование types.ModuleType для создания нового модуля, поскольку spec используется для установки как можно большего количества контролируемых импортом атрибутов модуля.

Added in version 3.5.

importlib.util.spec_from_loader(name, loader, *, origin=None, is_package=None)

Функция-фабрика для создания экземпляра ModuleSpec на основе загрузчика. Параметры имеют то же значение, что и для ModuleSpec. Функция использует доступные loader API, такие как InspectLoader.is_package(), для заполнения недостающей информации в спецификации.

Added in version 3.4.

importlib.util.spec_from_file_location(name, location, *, loader=None, submodule_search_locations=None)

Фабричная функция для создания экземпляра ModuleSpec на основе пути к файлу. Недостающая информация будет восполнена в спецификации за счет использования API загрузчика и подразумевания того, что модуль будет основан на файлах.

Added in version 3.4.

Изменено в версии 3.6: Принимает path-like object.

importlib.util.source_hash(source_bytes)

Возвращает хэш source_bytes в виде байтов. Файл, основанный на хэше .pyc, вставляет source_hash() содержимого соответствующего исходного файла в свой заголовок.

Added in version 3.7.

importlib.util._incompatible_extension_module_restrictions(*, disable_check)

Менеджер контекста, который может временно пропустить проверку совместимости для модулей расширения. По умолчанию проверка включена и будет неудачной, если однофазный модуль init импортируется в подинтерпретатор. Она также будет неудачной для многофазного модуля init, который явно не поддерживает GIL для каждого интерпретатора, при импорте в интерпретатор с собственным GIL.

Обратите внимание, что эта функция предназначена для необычных случаев, которые, скорее всего, со временем исчезнут. Вполне вероятно, что это не то, что вы искали.

Вы можете получить тот же эффект, что и эта функция, реализовав базовый интерфейс многофазного init (PEP 489) и солгав о поддержке нескольких интерпретаторов (или per-interpreter GIL).

Предупреждение

Использование этой функции для отключения проверки может привести к неожиданному поведению и даже сбоям. Ее следует использовать только при разработке модуля расширения.

Added in version 3.12.

class importlib.util.LazyLoader(loader)

Класс, который откладывает выполнение загрузчика модуля до тех пор, пока модуль не получит доступ к какому-либо атрибуту.

Этот класс единственно работает с загрузчиками, определяющими exec_module(), поскольку требуется контроль над тем, какой тип модуля используется для модуля. По тем же причинам метод create_module() загрузчика должен возвращать None или тип, для которого его атрибут __class__ может быть изменен, а также не использовать slots. Наконец, модули, подменяющие объект, помещенный в sys.modules, работать не будут, так как нет способа корректно заменить ссылки на модуль во всем интерпретаторе; при обнаружении такой подмены будет выдано сообщение ValueError.

Примечание

Для проектов, где время запуска критично, этот класс позволяет потенциально минимизировать затраты на загрузку модуля, если он никогда не используется. Для проектов, в которых время запуска не имеет большого значения, использование этого класса очень не рекомендуется из-за того, что сообщения об ошибках, созданные во время загрузки, будут отложены и, таким образом, появятся вне контекста.

Added in version 3.5.

Изменено в версии 3.6: Начали вызывать create_module(), убрав предупреждение о совместимости для importlib.machinery.BuiltinImporter и importlib.machinery.ExtensionFileLoader.

classmethod factory(loader)

Метод класса, возвращающий вызываемую переменную, которая создает ленивый загрузчик. Он предназначен для использования в ситуациях, когда загрузчик передается по классу, а не по экземпляру.

suffixes = importlib.machinery.SOURCE_SUFFIXES
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))

Примеры

Импорт программным способом

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

import importlib

itertools = importlib.import_module('itertools')

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

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

Обратите внимание, что если name является подмодулем (содержит точку), то importlib.util.find_spec() будет импортировать родительский модуль.

import importlib.util
import sys

# For illustrative purposes.
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:
    # If you chose to perform the actual import ...
    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 напрямую, воспользуйтесь следующим рецептом:

import importlib.util
import sys

# For illustrative purposes.
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)

Реализация ленивого импорта

В примере ниже показано, как реализовать ленивый импорт:

>>> import importlib.util
>>> import sys
>>> def lazy_import(name):
...     spec = importlib.util.find_spec(name)
...     loader = importlib.util.LazyLoader(spec.loader)
...     spec.loader = loader
...     module = importlib.util.module_from_spec(spec)
...     sys.modules[name] = module
...     loader.exec_module(module)
...     return module
...
>>> lazy_typing = lazy_import("typing")
>>> #lazy_typing is a real module object,
>>> #but it is not loaded in memory yet.
>>> lazy_typing.TYPE_CHECKING
False

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

Для глубокой настройки импорта обычно требуется реализовать importer. Это означает управление как finder, так и loader. Для искателей есть два варианта в зависимости от ваших потребностей: meta path finder или path entry finder. Первый - это то, что вы поместите на sys.meta_path, а второй - то, что вы создадите, используя path entry hook на sys.path_hooks, который работает с записями sys.path, чтобы потенциально создать искатель. Этот пример покажет вам, как зарегистрировать собственные импортеры, чтобы импорт использовал их (для создания собственного импортера читайте документацию по соответствующим классам, определенным в этом пакете):

import importlib.machinery
import sys

# For illustrative purposes only.
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
                  importlib.machinery.SOURCE_SUFFIXES)

# Setting up a meta path finder.
# Make sure to put the finder in the proper location in the list in terms of
# priority.
sys.meta_path.append(SpamMetaPathFinder)

# Setting up a path entry finder.
# Make sure to put the path hook in the proper location in the list in terms
# of priority.
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

Приближение importlib.import_module()

Сам импорт реализован в коде Python, что позволяет раскрыть большую часть механизма импорта через importlib. Ниже приводится примерная реализация 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