Документация Python неофициальный перевод

import.md

423 строк · 75.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.16/reference/import.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 5. Система импорта89Код Python в одном [модуле](https://python-all.ru/3.16/glossary.html#term-module) получает доступ к коду в другом модуле путем [импортирования](https://python-all.ru/3.16/glossary.html#term-importing) его. Оператор [`import`](https://python-all.ru/3.16/reference/simple_stmts.html#import) является наиболее распространенным способом вызова механизма импорта, но не единственным. Такие функции, как [`importlib.import_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.import_module) и встроенная [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__), также могут использоваться для вызова механизма импорта.1011Оператор [`import`](https://python-all.ru/3.16/reference/simple_stmts.html#import) объединяет две операции: он ищет указанный модуль, а затем привязывает результат этого поиска к имени в локальной области видимости. Операция поиска оператора `import` определяется как вызов функции [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__) с соответствующими аргументами. Возвращаемое значение `__import__()` используется для выполнения операции привязки имени оператора `import`. Подробности операции привязки имени приведены в описании оператора `import`.1213Прямой вызов [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__) выполняет только поиск модуля и, если он найден, операцию создания модуля. Хотя могут возникать некоторые побочные эффекты, такие как импорт родительских пакетов и обновление различных кешей (включая [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules)), только оператор [`import`](https://python-all.ru/3.16/reference/simple_stmts.html#import) выполняет операцию привязки имени.1415При выполнении оператора [`import`](https://python-all.ru/3.16/reference/simple_stmts.html#import) вызывается стандартная встроенная функция [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__). Другие механизмы вызова системы импорта (например, [`importlib.import_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.import_module)) могут обходить `__import__()` и использовать собственные решения для реализации семантики импорта.1617При первом импорте модуля Python ищет этот модуль и, если он найден, создает объект модуля [\[1\]](https://python-all.ru/3.16/reference/import.html#fnmo), инициализируя его. Если указанный модуль не найден, возбуждается исключение [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError). Python реализует различные стратегии поиска указанного модуля при вызове механизма импорта. Эти стратегии можно изменять и расширять с помощью различных хуков, описанных в следующих разделах.1819Изменено в версии 3.3: Система импорта была обновлена для полной реализации второй фазы [**PEP 302**](https://python-all.ru/3.16/reference/import.html). Больше не существует неявного механизма импорта – вся система импорта доступна через [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path). Кроме того, добавлена поддержка нативных пространств имен пакетов (см. [**PEP 420**](https://python-all.ru/3.16/reference/import.html)).2021## 5.1. [`importlib`](https://python-all.ru/3.16/library/importlib.html#module-importlib)2223Модуль [`importlib`](https://python-all.ru/3.16/library/importlib.html#module-importlib) предоставляет богатый API для взаимодействия с системой импорта. Например, [`importlib.import_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.import_module) предоставляет рекомендуемый, более простой API, чем встроенный [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__), для вызова механизма импорта. За дополнительными сведениями обращайтесь к документации библиотеки `importlib`.2425## 5.2. Пакеты2627Python has only one type of module object, and all modules are of this type, regardless of whether the module is implemented in Python, C, or something else. To help organize modules and provide a naming hierarchy, Python has a concept of [packages](https://python-all.ru/3.16/glossary.html#term-package).2829Можно представлять пакеты как каталоги в файловой системе, а модули – как файлы в этих каталогах, но не стоит воспринимать эту аналогию слишком буквально, поскольку пакеты и модули не обязательно происходят из файловой системы. В целях данной документации мы будем использовать эту удобную аналогию каталогов и файлов. Как и каталоги файловой системы, пакеты организованы иерархически, и пакеты могут содержать вложенные пакеты, а также обычные модули.3031Важно помнить, что все пакеты являются модулями, но не все модули являются пакетами. Или, иными словами, пакеты – это просто особый вид модуля. В частности, любой модуль, содержащий атрибут `__path__`, считается пакетом.3233Все модули имеют имя. Имена вложенных пакетов отделяются от имени родительского пакета точкой, как в стандартном синтаксисе доступа к атрибутам Python. Таким образом, может существовать пакет [`email`](https://python-all.ru/3.16/library/email.html#module-email), который содержит вложенный пакет [`email.mime`](https://python-all.ru/3.16/library/email.mime.html#module-email.mime), а внутри этого вложенного пакета – модуль [`email.mime.text`](https://python-all.ru/3.16/library/email.mime.html#module-email.mime.text).3435### 5.2.1. Обычные пакеты3637Python defines two types of packages, [regular packages](https://python-all.ru/3.16/glossary.html#term-regular-package) and [namespace packages](https://python-all.ru/3.16/glossary.html#term-namespace-package). Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an `__init__.py` file. When a regular package is imported, this `__init__.py` file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The `__init__.py` file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.3839Например, следующая структура файловой системы определяет пакет верхнего уровня `parent` с тремя вложенными пакетами:4041```python42parent/43    __init__.py44    one/45        __init__.py46    two/47        __init__.py48    three/49        __init__.py50```5152Импорт `parent.one` неявно выполнит `parent/__init__.py` и `parent/one/__init__.py`. Последующие импорты `parent.two` или `parent.three` выполнят `parent/two/__init__.py` и `parent/three/__init__.py` соответственно.5354A subdirectory inside a regular package that does not contain an `__init__.py` file is treated as an implicit [namespace package](https://python-all.ru/3.16/reference/import.html#reference-namespace-package) (a “namespace subpackage”) rooted in that parent. See [**PEP 420**](https://python-all.ru/3.16/reference/import.html) for the underlying specification.5556### 5.2.2. Пакеты пространств имен5758A namespace package is a composite of various [portions](https://python-all.ru/3.16/glossary.html#term-portion), where each portion contributes a subpackage to the parent package. Portions may reside in different locations on the file system. Portions may also be found in zip files, on the network, or anywhere else that Python searches during import. Namespace packages may or may not correspond directly to objects on the file system; they may be virtual modules that have no concrete representation.5960Пакеты пространств имен не используют обычный список для своего атрибута `__path__`. Вместо этого они используют пользовательский итерируемый тип, который автоматически выполняет новый поиск частей пакета при следующей попытке импорта в рамках этого пакета, если путь родительского пакета (или [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path) для пакета верхнего уровня) изменяется.6162В пакетах пространств имен нет файла `parent/__init__.py`. Фактически, при поиске импорта может быть найдено несколько каталогов `parent`, каждый из которых предоставляется разной частью. Таким образом, `parent/one` может физически не находиться рядом с `parent/two`. В этом случае Python создаст пакет пространства имен для пакета верхнего уровня `parent` всякий раз, когда импортируется сам этот пакет или любой из его вложенных пакетов.6364Namespace packages may also be nested inside a regular package. When the import system searches a regular package’s `__path__` and encounters a subdirectory that does not contain an `__init__.py` file, that subdirectory becomes a [portion](https://python-all.ru/3.16/glossary.html#term-portion) contributing to a namespace subpackage of the enclosing regular package.6566See also [**PEP 420**](https://python-all.ru/3.16/reference/import.html) for the namespace package specification.6768## 5.3. Поиск6970To begin the search, Python needs the [fully qualified](https://python-all.ru/3.16/glossary.html#term-qualified-name) name of the module (or package, but for the purposes of this discussion, the difference is immaterial) being imported. This name may come from various arguments to the [`import`](https://python-all.ru/3.16/reference/simple_stmts.html#import) statement, or from the parameters to the [`importlib.import_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.import_module) or [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__) functions.7172Это имя будет использоваться на различных этапах поиска импорта и может быть точечным путём к подмодулю, например `foo.bar.baz`. В этом случае Python сначала пытается импортировать `foo`, затем `foo.bar` и, наконец, `foo.bar.baz`. Если какой-либо из промежуточных импортов завершается неудачей, возбуждается [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError).7374### 5.3.1. Кеш модулей7576Первое место, проверяемое при поиске импорта, – это [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules). Это отображение служит кешем всех ранее импортированных модулей, включая промежуточные пути. Таким образом, если `foo.bar.baz` был ранее импортирован, `sys.modules` будет содержать записи для `foo`, `foo.bar` и `foo.bar.baz`. Каждый ключ будет иметь в качестве значения соответствующий объект модуля.7778Во время импорта имя модуля ищется в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules), и если оно присутствует, связанное значение является модулем, удовлетворяющим импорт, и процесс завершается. Однако если значением является `None`, то возбуждается [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError). Если имя модуля отсутствует, Python продолжает поиск модуля.7980[`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules) доступен для записи. Удаление ключа может не уничтожить связанный модуль (поскольку другие модули могут хранить на него ссылки), но это сделает недействительной запись кеша для указанного модуля, что заставит Python выполнить новый поиск этого модуля при следующем импорте. Ключ также можно присвоить `None`, что приведет к тому, что следующий импорт модуля завершится [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError).8182Однако будьте осторожны: если вы сохраните ссылку на объект модуля, сделаете недействительной его запись в кеше [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules), а затем повторно импортируете указанный модуль, два объекта модуля *не* будут одинаковыми. В отличие от этого, [`importlib.reload()`](https://python-all.ru/3.16/library/importlib.html#importlib.reload) будет повторно использовать *тот же* объект модуля и просто повторно инициализирует содержимое модуля, выполнив его код заново.8384### 5.3.2. Искатели и загрузчики8586Если именованный модуль не найден в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules), то вызывается протокол импорта Python для поиска и загрузки модуля. Этот протокол состоит из двух концептуальных объектов: [искателей](https://python-all.ru/3.16/glossary.html#term-finder) и [загрузчиков](https://python-all.ru/3.16/glossary.html#term-loader). Задача искателя – определить, может ли он найти именованный модуль, используя любую известную ему стратегию. Объекты, реализующие оба этих интерфейса, называются [импортерами](https://python-all.ru/3.16/glossary.html#term-importer) – они возвращают самих себя, когда обнаруживают, что могут загрузить запрошенный модуль.8788Python включает в себя несколько искателей и импортеров по умолчанию. Первый умеет находить встроенные модули, второй – замороженные модули. Третий искатель по умолчанию ищет модули в [пути импорта](https://python-all.ru/3.16/glossary.html#term-import-path). Путь импорта – это список расположений, которые могут указывать на пути файловой системы или zip-файлы. Его также можно расширить для поиска любого доступного ресурса, например, тех, что идентифицируются URL.8990Механизм импорта является расширяемым, поэтому можно добавлять новые искатели для расширения диапазона и области поиска модулей.9192Искатели на самом деле не загружают модули. Если они могут найти именованный модуль, они возвращают *спецификацию модуля* – инкапсуляцию информации, связанной с импортом модуля, которую затем использует механизм импорта при загрузке модуля.9394В следующих разделах протокол для искателей и загрузчиков описывается более подробно, включая то, как можно создавать и регистрировать новые для расширения механизма импорта.9596Изменено в версии 3.4: В предыдущих версиях Python искатели возвращали [загрузчики](https://python-all.ru/3.16/glossary.html#term-loader) напрямую, тогда как теперь они возвращают спецификации модулей, которые *содержат* загрузчики. Загрузчики по-прежнему используются при импорте, но имеют меньше обязанностей.9798### 5.3.3. Хуки импорта99100Механизм импорта разработан как расширяемый; основным механизмом для этого являются *хуки импорта*. Существует два типа хуков импорта: *мета-хуки* и *хуки пути импорта*.101102Мета-хуки вызываются в начале обработки импорта, до того, как произойдет любая другая обработка импорта, кроме поиска в кеше [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules). Это позволяет мета-хукам переопределять обработку [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path), замороженных модулей или даже встроенных модулей. Мета-хуки регистрируются путем добавления новых объектов искателей в [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path), как описано ниже.103104Хуки пути импорта вызываются как часть обработки [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path) (или `package.__path__`) в тот момент, когда встречается связанный с ними элемент пути. Хуки пути импорта регистрируются путем добавления новых вызываемых объектов в [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks), как описано ниже.105106### 5.3.4. Мета-путь107108Когда именованный модуль не найден в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules), Python затем ищет в [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path), который содержит список объектов искателей мета-пути. Эти искатели опрашиваются по порядку, чтобы выяснить, знают ли они, как обрабатывать именованный модуль. Искатели мета-пути должны реализовывать метод с именем [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec), который принимает три аргумента: имя, путь импорта и (опционально) целевой модуль. Искатель мета-пути может использовать любую стратегию по своему усмотрению, чтобы определить, может ли он обработать именованный модуль или нет.109110Если искатель мета-пути знает, как обрабатывать именованный модуль, он возвращает объект спецификации. Если он не может обработать именованный модуль, он возвращает `None`. Если обработка [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path) достигает конца своего списка, не вернув спецификацию, то возбуждается [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError). Любые другие возникшие исключения просто распространяются вверх, прерывая процесс импорта.111112Метод [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec) искателей мета-пути вызывается с двумя или тремя аргументами. Первый – это полное имя импортируемого модуля, например `foo.bar.baz`. Второй аргумент – это записи пути, используемые для поиска модуля. Для модулей верхнего уровня вторым аргументом является `None`, но для подмодулей или подпакетов вторым аргументом является значение атрибута `__path__` родительского пакета. Если соответствующий атрибут `__path__` недоступен, возбуждается [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError). Третий аргумент – это существующий объект модуля, который будет целью загрузки позже. Система импорта передает целевой модуль только во время перезагрузки.113114Мета-путь может обходиться несколько раз для одного запроса импорта. Например, предполагая, что ни один из задействованных модулей еще не был кеширован, импорт `foo.bar.baz` сначала выполнит импорт верхнего уровня, вызывая `mpf.find_spec("foo", None, None)` у каждого искателя мета-пути (`mpf`). После того, как `foo` был импортирован, `foo.bar` будет импортирован путем обхода мета-пути во второй раз с вызовом `mpf.find_spec("foo.bar", foo.__path__, None)`. Как только `foo.bar` будет импортирован, последний обход вызовет `mpf.find_spec("foo.bar.baz", foo.bar.__path__, None)`.115116Некоторые искатели мета-пути поддерживают только импорт верхнего уровня. Эти импортеры всегда будут возвращать `None`, если в качестве второго аргумента передано что-либо, кроме `None`.117118[`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path) по умолчанию Python имеет три искателя мета-пути: один умеет импортировать встроенные модули, один – замороженные модули и один – модули из [пути импорта](https://python-all.ru/3.16/glossary.html#term-import-path) (т.е. [искатель на основе пути](https://python-all.ru/3.16/glossary.html#term-path-based-finder)).119120Изменено в версии 3.4: Метод [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec) искателей мета-пути заменил `find_module()`, который теперь устарел. Хотя он продолжит работать без изменений, механизм импорта будет использовать его только в том случае, если искатель не реализует `find_spec()`.121122Изменено в версии 3.10: Использование `find_module()` системой импорта теперь вызывает [`ImportWarning`](https://python-all.ru/3.16/library/exceptions.html#ImportWarning).123124Изменено в версии 3.12: `find_module()` удалён. Вместо него используйте [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec).125126## 5.4. Загрузка127128Если (и когда) спецификация модуля найдена, механизм импорта использует её (и содержащийся в ней загрузчик) при загрузке модуля. Ниже приведено приблизительное описание того, что происходит во время части импорта, связанной с загрузкой:129130```python131module = None132if spec.loader is not None and hasattr(spec.loader, 'create_module'):133    # Предполагается, что 'exec_module' также будет определён в загрузчике.134    module = spec.loader.create_module(spec)135if module is None:136    module = ModuleType(spec.name)137# Здесь задаются атрибуты модуля, связанные с импортом:138_init_module_attrs(spec, module)139140if spec.loader is None:141    # не поддерживается142    raise ImportError143144sys.modules[spec.name] = module145try:146    spec.loader.exec_module(module)147except BaseException:148    try:149        del sys.modules[spec.name]150    except KeyError:151        pass152    raise153return sys.modules[spec.name]154```155156Обратите внимание на следующие детали:157158- Если в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules) уже существует объект модуля с указанным именем, импорт уже вернёт его.159- Модуль будет существовать в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules) до того, как загрузчик выполнит код модуля. Это крайне важно, потому что код модуля может (прямо или косвенно) импортировать сам себя; его добавление в `sys.modules` заранее предотвращает неограниченную рекурсию в худшем случае и множественную загрузку в лучшем.160- Если загрузка завершается ошибкой, модуль, вызвавший ошибку (и только он), удаляется из [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules). Любой модуль, уже находящийся в кеше `sys.modules`, а также любой модуль, который был успешно загружен как побочный эффект, должен оставаться в кеше. Это отличается от перезагрузки, где даже неудачно загруженный модуль остаётся в `sys.modules`.161- После создания модуля, но до его выполнения, механизм импорта устанавливает атрибуты модуля, связанные с импортом («\_init\_module\_attrs» в примере псевдокода выше), как описано в [следующем разделе](https://python-all.ru/3.16/reference/datamodel.html#import-mod-attrs).162- Выполнение модуля – ключевой момент загрузки, в ходе которого заполняется пространство имён модуля. Выполнение полностью делегируется загрузчику, который решает, что и как заполнять.163- Модуль, созданный во время загрузки и переданный в exec\_module(), может не совпадать с тем, что возвращается в конце импорта [\[2\]](https://python-all.ru/3.16/reference/import.html#fnlo).164165Изменено в версии 3.4: Система импорта взяла на себя стандартные обязанности загрузчиков. Ранее они выполнялись методом `importlib.abc.Loader.load_module`.166167Изменено в версии 3.15: Метод `load_module` больше не используется.168169### 5.4.1. Загрузчики170171Загрузчики модулей выполняют критическую функцию загрузки: выполнение модуля. Механизм импорта вызывает метод [`importlib.abc.Loader.exec_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.Loader.exec_module) с одним аргументом – объектом модуля, который нужно выполнить. Любое значение, возвращённое из `exec_module()`, игнорируется.172173Загрузчики должны удовлетворять следующим требованиям:174175- Если модуль является модулем Python (в отличие от встроенного модуля или динамически загружаемого расширения), загрузчик должен выполнить код модуля в глобальном пространстве имён модуля (`module.__dict__`).176- Если загрузчик не может выполнить модуль, он должен вызвать исключение [`ImportError`](https://python-all.ru/3.16/library/exceptions.html#ImportError), хотя любое другое исключение, возникшее во время [`exec_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.Loader.exec_module), будет распространено.177178Во многих случаях искатель и загрузчик могут быть одним и тем же объектом; в таких случаях метод [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec) просто возвращает спецификацию с загрузчиком, установленным в `self`.179180Загрузчики модулей могут реализовать метод [`create_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.Loader.create_module), чтобы принять участие в создании объекта модуля во время загрузки. Он принимает один аргумент – спецификацию модуля – и возвращает новый объект модуля для использования во время загрузки. `create_module()` не нужно устанавливать какие-либо атрибуты объекта модуля. Если метод возвращает `None`, механизм импорта создаст новый модуль самостоятельно.181182Добавлено в версии 3.4: Метод [`create_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.Loader.create_module) загрузчиков.183184Изменено в версии 3.4: Метод `importlib.abc.Loader.load_module` был заменён на [`exec_module()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.Loader.exec_module), и механизм импорта взял на себя все стандартные обязанности по загрузке.185186Для совместимости с существующими загрузчиками механизм импорта будет использовать метод `load_module()` загрузчиков, если он существует и загрузчик не реализует также `exec_module()`. Однако `load_module()` устарел, и загрузчики должны реализовать `exec_module()` вместо него.187188Метод `load_module()` должен реализовывать всю описанную выше стандартную функциональность загрузки в дополнение к выполнению модуля. Применяются все те же ограничения с некоторыми дополнительными уточнениями:189190- Если в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules) уже существует объект модуля с указанным именем, загрузчик должен использовать этот существующий модуль. (В противном случае [`importlib.reload()`](https://python-all.ru/3.16/library/importlib.html#importlib.reload) не будет работать корректно.) Если именованный модуль не существует в `sys.modules`, загрузчик должен создать новый объект модуля и добавить его в `sys.modules`.191- Модуль *должен* существовать в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules) до того, как загрузчик выполнит код модуля, чтобы предотвратить неограниченную рекурсию или многократную загрузку.192- Если загрузка завершается ошибкой, загрузчик должен удалить любые модули, которые он вставил в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules), но он должен удалить **только** модуль(и), загрузка которого завершилась ошибкой, и только если загрузчик сам явно загрузил этот(и) модуль(и).193194Изменено в версии 3.5: Исключение [`DeprecationWarning`](https://python-all.ru/3.16/library/exceptions.html#DeprecationWarning) возбуждается, когда `exec_module()` определён, а `create_module()` – нет.195196Изменено в версии 3.6: Исключение [`ImportError`](https://python-all.ru/3.16/library/exceptions.html#ImportError) возбуждается, когда `exec_module()` определён, а `create_module()` – нет.197198Изменено в версии 3.10: Использование `load_module()` приведёт к возбуждению [`ImportWarning`](https://python-all.ru/3.16/library/exceptions.html#ImportWarning).199200### 5.4.2. Подмодули201202Когда подмодуль загружается с помощью любого механизма (например, API `importlib`, операторов `import` или `import-from`, или встроенной `__import__()`), в пространстве имён родительского модуля создаётся связывание с объектом подмодуля. Например, если пакет `spam` содержит подмодуль `foo`, то после импорта `spam.foo` у `spam` будет атрибут `foo`, который связан с подмодулем. Допустим, имеется следующая структура каталогов:203204```python205spam/206    __init__.py207    foo.py208```209210и `spam/__init__.py` содержит следующую строку:211212```python213from .foo import Foo214```215216тогда выполнение следующего кода помещает связывания имён для `foo` и `Foo` в модуль `spam`:217218```python219>>> import spam220>>> spam.foo221<module 'spam.foo' from '/tmp/imports/spam/foo.py'>222>>> spam.Foo223<class 'spam.foo.Foo'>224```225226Учитывая привычные правила связывания имён в Python, это может показаться удивительным, но на самом деле это фундаментальная особенность системы импорта. Сохраняется следующий инвариант: если имеются `sys.modules['spam']` и `sys.modules['spam.foo']` (как после импорта выше), то второй должен быть атрибутом `foo` первого.227228### 5.4.3. Спецификации модулей229230Механизм импорта использует различную информацию о каждом модуле во время импорта, особенно перед загрузкой. Большая часть этой информации является общей для всех модулей. Назначение спецификации модуля – инкапсулировать эту связанную с импортом информацию для каждого модуля отдельно.231232Использование спецификации во время импорта позволяет передавать состояние между компонентами системы импорта, например, между искателем, который создаёт спецификацию модуля, и загрузчиком, который её выполняет. Самое главное, это позволяет механизму импорта выполнять стандартные операции загрузки, тогда как без спецификации модуля эта ответственность лежала на загрузчике.233234Спецификация модуля доступна как [`module.__spec__`](https://python-all.ru/3.16/reference/datamodel.html#module.__spec__). Установка `__spec__` соответствующим образом в равной степени применима к [модулям, инициализируемым при запуске интерпретатора](https://python-all.ru/3.16/reference/toplevel_components.html#programs). Исключением является `__main__`, где `__spec__` [в некоторых случаях устанавливается в None](https://python-all.ru/3.16/reference/import.html#main-spec).235236Подробнее о содержимом спецификации модуля см. [`ModuleSpec`](https://python-all.ru/3.16/library/importlib.html#importlib.machinery.ModuleSpec).237238Добавлено в версии 3.4.239240### 5.4.4. Атрибуты \_\_path\_\_ модулей241242Атрибут [`__path__`](https://python-all.ru/3.16/reference/datamodel.html#module.__path__) должен представлять собой (возможно, пустую) [последовательность](https://python-all.ru/3.16/glossary.html#term-sequence) строк, перечисляющих расположения, где будут найдены подмодули пакета. По определению, если у модуля есть атрибут `__path__`, то это [пакет](https://python-all.ru/3.16/glossary.html#term-package).243244Атрибут [`__path__`](https://python-all.ru/3.16/reference/datamodel.html#module.__path__) пакета используется при импорте его подпакетов. В механизме импорта он работает практически так же, как [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path), то есть предоставляет список расположений для поиска модулей во время импорта. Однако `__path__` обычно гораздо более ограничен, чем `sys.path`.245246Те же правила, что применяются к [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path), действуют и для `__path__` пакета. [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks) (описаны ниже) используются при обходе `__path__` пакета.247248Файл `__init__.py` пакета может устанавливать или изменять атрибут [`__path__`](https://python-all.ru/3.16/reference/datamodel.html#module.__path__) пакета, и именно так обычно реализовывались пространства имён пакетов до [**PEP 420**](https://python-all.ru/3.16/reference/import.html). С принятием [**PEP 420**](https://python-all.ru/3.16/reference/import.html) пространства имён пакетов больше не требуют файлов `__init__.py`, содержащих только код манипуляции `__path__`; механизм импорта автоматически устанавливает `__path__` правильно для пространства имён пакета.249250### 5.4.5. Строковые представления модулей251252По умолчанию все модули имеют пригодное строковое представление, однако в зависимости от установленных выше атрибутов и спецификации модуля можно более явно управлять строковым представлением объектов модулей.253254Если у модуля есть спецификация (`__spec__`), механизм импорта попытается сгенерировать строковое представление на её основе. Если это не удаётся или спецификация отсутствует, система импорта создаст строковое представление по умолчанию, используя любую доступную информацию о модуле. Она попытается использовать `module.__name__`, `module.__file__` и `module.__loader__` в качестве входных данных для строкового представления, с умолчаниями для отсутствующей информации.255256Ниже приведены точные правила:257258- Если у модуля есть атрибут `__spec__`, для генерации строкового представления используется информация из спецификации. Учитываются атрибуты «name», «loader», «origin» и «has\_location».259- Если у модуля есть атрибут `__file__`, он используется как часть строкового представления модуля.260- Если у модуля нет `__file__`, но есть `__loader__`, который не равен `None`, то строковое представление загрузчика используется как часть строкового представления модуля.261- В противном случае в строковом представлении используется просто `__name__` модуля.262263Изменено в версии 3.12: Использование `module_repr()`, устаревшее с Python 3.4, было удалено в Python 3.12 и больше не вызывается при формировании строкового представления модуля.264265### 5.4.6. Инвалидация кэшированного байт-кода266267Прежде чем Python загрузит кэшированный байт-код из файла `.pyc`, он проверяет, актуален ли кэш относительно исходного файла `.py`. По умолчанию Python делает это, сохраняя метку времени последнего изменения и размер исходного файла в кэш-файле при его записи. Во время выполнения система импорта затем проверяет кэш-файл, сверяя сохранённые метаданные в кэш-файле с метаданными исходного файла.268269Python также поддерживает кэш-файлы на основе хеша, в которых вместо метаданных хранится хеш содержимого исходного файла. Существует два варианта таких `.pyc` файлов: проверяемые и непроверяемые. Для проверяемых `.pyc` файлов Python проверяет кэш-файл, хешируя исходный файл и сравнивая полученный хеш с хешем в кэш-файле. Если проверяемый кэш-файл на основе хеша оказывается недействительным, Python пересоздаёт его и записывает новый проверяемый кэш-файл на основе хеша. Для непроверяемых `.pyc` файлов Python просто считает кэш-файл действительным, если он существует. Поведение проверки `.pyc` файлов на основе хеша можно переопределить с помощью флага [`--check-hash-based-pycs`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-check-hash-based-pycs).270271Изменено в версии 3.7: Добавлены `.pyc` файлы на основе хеша. Ранее Python поддерживал только инвалидацию кэшей байт-кода на основе временных меток.272273## 5.5. Искатель на основе путей274275Как упоминалось ранее, Python включает несколько искателей мета-путей по умолчанию. Один из них, называемый [искатель на основе путей](https://python-all.ru/3.16/glossary.html#term-path-based-finder) ([`PathFinder`](https://python-all.ru/3.16/library/importlib.html#importlib.machinery.PathFinder)), ищет в [пути импорта](https://python-all.ru/3.16/glossary.html#term-import-path), который содержит список [записей пути](https://python-all.ru/3.16/glossary.html#term-path-entry). Каждая запись пути указывает расположение для поиска модулей.276277Сам искатель на основе путей не знает, как импортировать что-либо. Вместо этого он обходит отдельные записи пути, связывая каждую из них с искателем записей пути, который знает, как обрабатывать этот конкретный тип пути.278279Набор искателей записей пути по умолчанию реализует всю семантику поиска модулей в файловой системе, обрабатывая специальные типы файлов, такие как исходный код Python (файлы `.py`), байт-код Python (файлы `.pyc`) и разделяемые библиотеки (например, файлы `.so`). Если это поддерживается модулем [`zipimport`](https://python-all.ru/3.16/library/zipimport.html#module-zipimport) из стандартной библиотеки, искатели записей пути по умолчанию также загружают все эти типы файлов (кроме разделяемых библиотек) из zip-файлов.280281Записи пути не обязаны ограничиваться расположениями в файловой системе. Они могут ссылаться на URL, запросы к базе данных или любые другие расположения, которые можно указать в виде строки.282283Искатель на основе путей предоставляет дополнительные перехватчики и протоколы, позволяющие расширять и настраивать типы искомых записей пути. Например, если требуется поддерживать записи пути в виде сетевых URL, можно написать перехватчик, реализующий семантику HTTP для поиска модулей в вебе. Этот перехватчик (вызываемый объект) вернёт [искатель записей пути](https://python-all.ru/3.16/glossary.html#term-path-entry-finder), поддерживающий описанный ниже протокол, который затем будет использован для получения загрузчика модуля из веба.284285Предупреждение: в этом и предыдущем разделах используется термин *finder (искатель)*, различая их с помощью терминов [искатель мета-путей](https://python-all.ru/3.16/glossary.html#term-meta-path-finder) и [искатель записей пути](https://python-all.ru/3.16/glossary.html#term-path-entry-finder). Эти два типа искателей очень похожи, поддерживают схожие протоколы и действуют схожим образом в процессе импорта, однако важно помнить, что между ними есть тонкие различия. В частности, искатели мета-путей работают в начале процесса импорта, начиная с обхода [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path).286287Напротив, искатели записей пути в некотором смысле являются деталью реализации искателя на основе путей, и на самом деле, если бы искатель на основе путей был удалён из [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path), ни одна из семантик искателя записей пути не была бы задействована.288289### 5.5.1. Искатели записей пути290291[Искатель на основе путей](https://python-all.ru/3.16/glossary.html#term-path-based-finder) отвечает за поиск и загрузку модулей и пакетов Python, расположение которых задаётся строковой [записью пути](https://python-all.ru/3.16/glossary.html#term-path-entry). Большинство записей пути указывают на расположения в файловой системе, но не обязаны ограничиваться этим.292293Будучи искателем мета-путей, [искатель на основе путей](https://python-all.ru/3.16/glossary.html#term-path-based-finder) реализует протокол [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec), описанный ранее, однако он также предоставляет дополнительные перехватчики, которые можно использовать для настройки того, как модули находятся и загружаются из [пути импорта](https://python-all.ru/3.16/glossary.html#term-import-path).294295[Искатель на основе путей](https://python-all.ru/3.16/glossary.html#term-path-based-finder) использует три переменные: [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path), [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks) и [`sys.path_importer_cache`](https://python-all.ru/3.16/library/sys.html#sys.path_importer_cache). Также используются атрибуты `__path__` объектов пакетов. Они предоставляют дополнительные способы настройки механизма импорта.296297[`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path) содержит список строк, предоставляющих расположения для поиска модулей и пакетов. Он инициализируется из переменной окружения [`PYTHONPATH`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONPATH) и различных других умолчаний, зависящих от установки и реализации. Записи в `sys.path` могут указывать на каталоги в файловой системе, zip-файлы и потенциально другие «расположения» (см. модуль [`site`](https://python-all.ru/3.16/library/site.html#module-site)), которые следует искать для модулей, например URL или запросы к базам данных. В `sys.path` должны присутствовать только строки; все остальные типы данных игнорируются.298299[Искатель на основе путей](https://python-all.ru/3.16/glossary.html#term-path-based-finder) является [искателем мета-путей](https://python-all.ru/3.16/glossary.html#term-meta-path-finder), поэтому механизм импорта начинает поиск [пути импорта](https://python-all.ru/3.16/glossary.html#term-import-path) вызовом метода [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.machinery.PathFinder.find_spec) искателя на основе путей, как описано ранее. Когда аргумент `path` для `find_spec()` задан, это будет список строковых путей для обхода – обычно атрибут `__path__` пакета для импорта внутри этого пакета. Если аргумент `path` равен `None`, это указывает на импорт верхнего уровня, и используется [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path).300301The path based finder iterates over every entry in the search path, and for each of these, looks for an appropriate [path entry finder](https://python-all.ru/3.16/glossary.html#term-path-entry-finder) ([`PathEntryFinder`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.PathEntryFinder)) for the path entry. Because this can be an expensive operation (e.g. there may be `stat()` call overheads for this search), the path based finder maintains a cache mapping path entries to path entry finders. This cache is maintained in [`sys.path_importer_cache`](https://python-all.ru/3.16/library/sys.html#sys.path_importer_cache) (despite the name, this cache actually stores finder objects rather than being limited to [importer](https://python-all.ru/3.16/glossary.html#term-importer) objects). In this way, the expensive search for a particular [path entry](https://python-all.ru/3.16/glossary.html#term-path-entry) location’s path entry finder need only be done once. User code is free to remove cache entries from `sys.path_importer_cache` forcing the path based finder to perform the path entry search again.302303If the path entry is not present in the cache, the path based finder iterates over every callable in [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks). Each of the [path entry hooks](https://python-all.ru/3.16/glossary.html#term-path-entry-hook) in this list is called with a single argument, the path entry to be searched. This callable may either return a [path entry finder](https://python-all.ru/3.16/glossary.html#term-path-entry-finder) that can handle the path entry, or it may raise [`ImportError`](https://python-all.ru/3.16/library/exceptions.html#ImportError). An `ImportError` is used by the path based finder to signal that the hook cannot find a path entry finder for that [path entry](https://python-all.ru/3.16/glossary.html#term-path-entry). The exception is ignored and [import path](https://python-all.ru/3.16/glossary.html#term-import-path) iteration continues. The hook should expect either a string or bytes object; the encoding of bytes objects is up to the hook (e.g. it may be a file system encoding, UTF-8, or something else), and if the hook cannot decode the argument, it should raise `ImportError`.304305If [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks) iteration ends with no [path entry finder](https://python-all.ru/3.16/glossary.html#term-path-entry-finder) being returned, then the path based finder’s [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.machinery.PathFinder.find_spec) method will store `None` in [`sys.path_importer_cache`](https://python-all.ru/3.16/library/sys.html#sys.path_importer_cache) (to indicate that there is no finder for this path entry) and return `None`, indicating that this [meta path finder](https://python-all.ru/3.16/glossary.html#term-meta-path-finder) could not find the module.306307If a [path entry finder](https://python-all.ru/3.16/glossary.html#term-path-entry-finder) *is* returned by one of the [path entry hook](https://python-all.ru/3.16/glossary.html#term-path-entry-hook) callables on [`sys.path_hooks`](https://python-all.ru/3.16/library/sys.html#sys.path_hooks), then the following protocol is used to ask the finder for a module spec, which is then used when loading the module.308309Текущий рабочий каталог, обозначаемый пустой строкой, обрабатывается немного иначе, чем другие записи в [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path). Во-первых, если текущий рабочий каталог не удаётся определить или он не существует, в [`sys.path_importer_cache`](https://python-all.ru/3.16/library/sys.html#sys.path_importer_cache) не сохраняется никакого значения. Во-вторых, значение для текущего рабочего каталога определяется заново при каждом поиске модуля. В-третьих, путь, используемый для `sys.path_importer_cache` и возвращаемый [`importlib.machinery.PathFinder.find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.machinery.PathFinder.find_spec), будет фактическим текущим рабочим каталогом, а не пустой строкой.310311### 5.5.2. Протокол искателя записей пути312313Для поддержки импорта модулей и инициализированных пакетов, а также для внесения частей в пространственно-именованные пакеты, искатели записей пути должны реализовывать метод [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.PathEntryFinder.find_spec).314315[`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.PathEntryFinder.find_spec) принимает два аргумента: полное имя импортируемого модуля и (необязательный) целевой модуль. `find_spec()` возвращает полностью заполненную спецификацию для модуля. В этой спецификации всегда будет установлен атрибут «loader» (за одним исключением).316317To indicate to the import machinery that the spec represents a namespace [portion](https://python-all.ru/3.16/glossary.html#term-portion), the path entry finder sets `submodule_search_locations` to a list containing the portion.318319Изменено в версии 3.4: [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.PathEntryFinder.find_spec) заменил `find_loader()` и `find_module()`, оба из которых теперь устарели, но будут использоваться, если `find_spec()` не определён.320321Более старые искатели записей пути могут реализовывать один из двух устаревших методов вместо `find_spec()`. Эти методы по-прежнему учитываются для обратной совместимости. Однако, если на искателе записей пути реализован `find_spec()`, устаревшие методы игнорируются.322323`find_loader()` takes one argument, the fully qualified name of the module being imported. `find_loader()` returns a 2-tuple where the first item is the loader and the second item is a namespace [portion](https://python-all.ru/3.16/glossary.html#term-portion).324325Для обратной совместимости с другими реализациями протокола импорта многие искатели записей пути также поддерживают тот же традиционный метод `find_module()`, который поддерживают искатели метапути. Однако методы `find_module()` искателей записей пути никогда не вызываются с аргументом `path` (предполагается, что они записывают соответствующую информацию о пути из первоначального вызова хука пути).326327Метод `find_module()` у искателей записей пути устарел, так как он не позволяет искателю записей пути вносить части в пространственно-именованные пакеты. Если на искателе записей пути существуют и `find_loader()`, и `find_module()`, система импорта всегда будет вызывать `find_loader()` в предпочтение `find_module()`.328329Изменено в версии 3.10: Вызовы `find_module()` и `find_loader()` системой импорта будут возбуждать [`ImportWarning`](https://python-all.ru/3.16/library/exceptions.html#ImportWarning).330331Изменено в версии 3.12: `find_module()` и `find_loader()` были удалены.332333## 5.6. Замена стандартной системы импорта334335Самый надёжный механизм замены всей системы импорта – удалить содержимое по умолчанию из [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path), полностью заменив их пользовательским хуком метапути.336337Если допустимо изменить только поведение операторов импорта, не затрагивая другие API, обращающиеся к системе импорта, то замены встроенной функции [`__import__()`](https://python-all.ru/3.16/library/functions.html#import__) может быть достаточно.338339Чтобы выборочно предотвратить импорт некоторых модулей из хука на раннем этапе метапути (вместо полного отключения стандартной системы импорта), достаточно возбудить [`ModuleNotFoundError`](https://python-all.ru/3.16/library/exceptions.html#ModuleNotFoundError) непосредственно из [`find_spec()`](https://python-all.ru/3.16/library/importlib.html#importlib.abc.MetaPathFinder.find_spec), а не возвращать `None`. Последнее означает, что поиск по метапути должен продолжаться, тогда как возбуждение исключения немедленно его прекращает.340341## 5.7. Относительный импорт в пакетах342343Относительный импорт использует начальные точки. Одна начальная точка означает относительный импорт, начиная с текущего пакета. Две или более начальных точек означают относительный импорт к родительским пакетам текущего пакета, один уровень на каждую точку после первой. Например, при следующей структуре пакета:344345```python346package/347    __init__.py348    subpackage1/349        __init__.py350        moduleX.py351        moduleY.py352    subpackage2/353        __init__.py354        moduleZ.py355    moduleA.py356```357358В любом из `subpackage1/moduleX.py` или `subpackage1/__init__.py` следующие относительные импорты допустимы:359360```python361from .moduleY import spam362from .moduleY import spam as ham363from . import moduleY364from ..subpackage1 import moduleY365from ..subpackage2.moduleZ import eggs366from ..moduleA import foo367```368369Абсолютный импорт может использовать синтаксис `import <>` или `from <> import <>`, но относительный импорт может использовать только вторую форму; причина в том, что:370371```python372import XXX.YYY.ZZZ373```374375должен предоставлять `XXX.YYY.ZZZ` как допустимое выражение, тогда как .moduleY не является допустимым выражением.376377## 5.8. Особые соображения для \_\_main\_\_378379The [`__main__`](https://python-all.ru/3.16/library/__main__.html#module-__main__) module is a special case relative to Python’s import system. As noted [elsewhere](https://python-all.ru/3.16/reference/toplevel_components.html#programs), the `__main__` module is directly initialized at interpreter startup, much like [`sys`](https://python-all.ru/3.16/library/sys.html#module-sys) and [`builtins`](https://python-all.ru/3.16/library/builtins.html#module-builtins). However, unlike those two, it doesn’t strictly qualify as a built-in module. This is because the manner in which `__main__` is initialized depends on the flags and other options with which the interpreter is invoked.380381### 5.8.1. \_\_main\_\_.\_\_spec\_\_382383В зависимости от того, как инициализируется [`__main__`](https://python-all.ru/3.16/library/__main__.html#module-__main__), `__main__.__spec__` устанавливается соответствующим образом или в `None`.384385Когда Python запускается с опцией [`-m`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-m), `__spec__` устанавливается в спецификацию модуля соответствующего модуля или пакета. `__spec__` также заполняется, когда модуль `__main__` загружается при выполнении каталога, zip-файла или другой записи [`sys.path`](https://python-all.ru/3.16/library/sys.html#sys.path).386387In [the remaining cases](https://python-all.ru/3.16/using/cmdline.html#using-on-interface-options) `__main__.__spec__` is set to `None`, as the code used to populate the [`__main__`](https://python-all.ru/3.16/library/__main__.html#module-__main__) does not correspond directly with an importable module:388389- интерактивная подсказка390- [`-c`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-c) опция391- запуск из stdin392- запуск напрямую из исходного или байт-код файла393394Обратите внимание, что `__main__.__spec__` всегда `None` в последнем случае, *даже если* файл технически можно импортировать напрямую как модуль. Используйте флаг [`-m`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-m), если нужны корректные метаданные модуля в [`__main__`](https://python-all.ru/3.16/library/__main__.html#module-__main__).395396Также обратите внимание, что даже если `__main__` соответствует импортируемому модулю и `__main__.__spec__` установлено соответствующим образом, они всё равно считаются *отдельными* модулями. Это связано с тем, что блоки, защищённые проверками `if __name__ == "__main__":`, выполняются только тогда, когда модуль используется для заполнения пространства имён `__main__`, а не при обычном импорте.397398## 5.9. Ссылки399400Механизм импорта значительно изменился с первых дней Python. Оригинальная [спецификация пакетов](https://python-all.ru/3.16/reference/import.html) всё ещё доступна для чтения, хотя некоторые детали изменились после написания этого документа.401402Оригинальная спецификация для [`sys.meta_path`](https://python-all.ru/3.16/library/sys.html#sys.meta_path) была [**PEP 302**](https://python-all.ru/3.16/reference/import.html), с последующим расширением в [**PEP 420**](https://python-all.ru/3.16/reference/import.html).403404[**PEP 420**](https://python-all.ru/3.16/reference/import.html) представил [пространства имён пакетов](https://python-all.ru/3.16/glossary.html#term-namespace-package) для Python 3.3. [**PEP 420**](https://python-all.ru/3.16/reference/import.html) также представил протокол `find_loader()` как альтернативу `find_module()`.405406[**PEP 366**](https://python-all.ru/3.16/reference/import.html) описывает добавление атрибута `__package__` для явных относительных импортов в главных модулях.407408[**PEP 328**](https://python-all.ru/3.16/reference/import.html) ввёл абсолютные и явные относительные импорты и изначально предложил `__name__` для семантики, которую [**PEP 366**](https://python-all.ru/3.16/reference/import.html) в конечном итоге определил для `__package__`.409410[**PEP 338**](https://python-all.ru/3.16/reference/import.html) определяет выполнение модулей как сценариев.411412[**PEP 451**](https://python-all.ru/3.16/reference/import.html) добавляет инкапсуляцию состояния импорта для каждого модуля в объекты спецификации. Он также перекладывает большую часть шаблонных обязанностей загрузчиков обратно на механизм импорта. Эти изменения позволяют устаревание нескольких API в системе импорта, а также добавление новых методов для искателей и загрузчиков.413414Сноски415416\[[1](https://python-all.ru/3.16/reference/import.html#id1)\]417418См. [`types.ModuleType`](https://python-all.ru/3.16/library/types.html#types.ModuleType).419420\[[2](https://python-all.ru/3.16/reference/import.html#id3)\]421422Реализация importlib избегает прямого использования возвращаемого значения. Вместо этого она получает объект модуля, выполняя поиск имени модуля в [`sys.modules`](https://python-all.ru/3.16/library/sys.html#sys.modules). Косвенный эффект этого заключается в том, что импортированный модуль может заменить себя в `sys.modules`. Это поведение, зависящее от реализации, которое не гарантируется в других реализациях Python.423