5. Система импорта

Код Python в одном модуле получает доступ к коду в другом модуле в процессе его импортирования. Инструкция import — самый распространённый способ вызвать механизм импорта, но не единственный. Для этого также можно использовать, например, функцию importlib.import_module() или встроенную функцию __import__().

Инструкция import объединяет две операции: она ищет модуль с указанным именем, а затем связывает результат поиска с именем в локальной области видимости. Операция поиска в инструкции import определяется как вызов функции __import__() с соответствующими аргументами. Возвращаемое значение __import__() используется для выполнения операции связывания имени в инструкции import. Точные сведения об этой операции связывания имени см. в описании инструкции import.

Прямой вызов __import__() выполняет только поиск модуля и, если он найден, создание объекта модуля. Могут возникать некоторые побочные эффекты, например импорт родительских пакетов и обновление различных кэшей (включая sys.modules), но операцию связывания имени выполняет только инструкция import.

Когда выполняется инструкция import, вызывается стандартная встроенная функция __import__(). Другие механизмы вызова системы импорта (например, importlib.import_module()) могут обойти __import__() и реализовать семантику импорта собственными средствами.

Когда модуль импортируется впервые, Python ищет его и, если находит, создаёт объект модуля [1] и инициализирует его. Если модуль с указанным именем найти не удаётся, возбуждается исключение ModuleNotFoundError. При вызове механизма импорта Python использует различные стратегии поиска модуля с указанным именем. Эти стратегии можно изменять и расширять с помощью различных обработчиков импорта, описанных в разделах ниже.

Изменено в версии 3.3: Система импорта была обновлена и теперь полностью реализует вторую фазу PEP 302. Неявного механизма импорта больше нет — вся система импорта доступна через sys.meta_path. Кроме того, реализована встроенная поддержка пакетов пространства имён (см. PEP 420).

5.1. importlib

Модуль importlib предоставляет богатый API для взаимодействия с системой импорта. Например, importlib.import_module() — рекомендуемый API для вызова механизма импорта, более простой, чем у встроенной функции __import__(). Дополнительные сведения см. в документации библиотеки importlib.

5.2. Пакеты

В Python есть только один тип объектов модулей, и все модули принадлежат к этому типу независимо от того, реализованы ли они на Python, на C или на чём-то ещё. Чтобы помочь организовать модули и обеспечить иерархию имён, в Python есть понятие пакетов.

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

Важно помнить, что все пакеты являются модулями, но не все модули являются пакетами. Иначе говоря, пакеты — это просто особый вид модулей. А именно, любой модуль, содержащий атрибут __path__, считается пакетом.

У всех модулей есть имя. Имена подпакетов отделяются от имени родительского пакета точкой, подобно стандартному синтаксису доступа к атрибутам в Python. Так, у вас может быть пакет email, у которого, в свою очередь, есть подпакет email.mime, а в этом подпакете — модуль email.mime.text.

5.2.1. Обычные пакеты

Python определяет два типа пакетов: обычные пакеты и пакеты пространства имён. Обычные пакеты — это традиционные пакеты, какими они были в Python 3.2 и более ранних версиях. Обычный пакет, как правило, реализуется в виде каталога, содержащего файл __init__.py. При импорте обычного пакета этот файл __init__.py неявно выполняется, а определённые в нём объекты связываются с именами в пространстве имён пакета. Файл __init__.py может содержать тот же код Python, что и любой другой модуль, а при импорте Python добавит к модулю некоторые дополнительные атрибуты.

Например, следующая структура файловой системы определяет пакет верхнего уровня parent с тремя подпакетами:

parent/
    __init__.py
    one/
        __init__.py
    two/
        __init__.py
    three/
        __init__.py

Импорт parent.one неявно выполнит parent/__init__.py и parent/one/__init__.py. Последующие импорты parent.two или parent.three выполнят parent/two/__init__.py и parent/three/__init__.py соответственно.

Подкаталог внутри обычного пакета, не содержащий файла __init__.py, рассматривается как неявный пакет пространства имён («подпакет пространства имён») с корнем в этом родительском пакете. Лежащую в основе спецификацию см. в PEP 420.

5.2.2. Пакеты пространства имён

Пакет пространства имён составлен из различных частей, каждая из которых вносит в родительский пакет один подпакет. Части могут находиться в разных местах файловой системы. Их можно также найти в zip-файлах, в сети или где-либо ещё, где Python выполняет поиск при импорте. Пакеты пространства имён могут как напрямую соответствовать объектам файловой системы, так и не соответствовать им. Они могут быть виртуальными модулями, не имеющими конкретного представления.

Пакеты пространства имён не используют для своего атрибута __path__ обычный список. Вместо этого они используют собственный итерируемый тип, который при следующей попытке импорта внутри этого пакета автоматически выполняет новый поиск частей пакета, если путь их родительского пакета (или sys.path для пакета верхнего уровня) изменился.

У пакетов пространства имён нет файла parent/__init__.py. Более того, при поиске для импорта может найтись несколько каталогов parent, каждый из которых предоставлен отдельной частью. Поэтому parent/one может физически находиться не рядом с parent/two. В этом случае Python создаёт пакет пространства имён для пакета верхнего уровня parent всякий раз, когда импортируется он сам или один из его подпакетов.

Пакеты пространства имён могут также быть вложены в обычный пакет. Когда система импорта просматривает __path__ обычного пакета и встречает подкаталог, не содержащий файла __init__.py, этот подкаталог становится частью, вносящей вклад в подпакет пространства имён охватывающего обычного пакета.

См. также PEP 420 — спецификацию пакетов пространства имён.

5.3. Поиск

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

Это имя будет использоваться на различных этапах поиска при импорте и может быть путём к подмодулю в точечной нотации, например foo.bar.baz. В этом случае Python сначала пытается импортировать foo, затем foo.bar и, наконец, foo.bar.baz. Если какой-либо из промежуточных импортов завершается неудачей, возбуждается исключение ModuleNotFoundError.

5.3.1. Кэш модулей

Первое место, которое проверяется при поиске для импорта, — sys.modules. Это отображение служит кэшем всех ранее импортированных модулей, включая промежуточные пути. Так, если ранее был импортирован foo.bar.baz, то sys.modules будет содержать записи для foo, foo.bar и foo.bar.baz. Значением каждого ключа служит соответствующий объект модуля.

При импорте имя модуля ищется в sys.modules, и если оно там есть, то связанное с ним значение и есть модуль, удовлетворяющий импорту, а процесс на этом завершается. Однако если значение равно None, возбуждается исключение ModuleNotFoundError. Если имя модуля отсутствует, Python продолжит поиск этого модуля.

sys.modules доступен для записи. Удаление ключа не обязательно уничтожит связанный с ним модуль (поскольку другие модули могут хранить на него ссылки), но сделает недействительной запись кэша для этого модуля, и при следующем импорте Python будет искать его заново. Ключу также можно присвоить None, чтобы следующий импорт модуля завершился исключением ModuleNotFoundError.

Но будьте осторожны: если вы сохраните ссылку на объект модуля, сделаете недействительной его запись в sys.modules, а затем заново импортируете этот модуль, то два объекта модуля не будут одним и тем же объектом. Напротив, importlib.reload() использует тот же самый объект модуля и просто заново инициализирует его содержимое, повторно выполняя код модуля.

5.3.2. Поисковики и загрузчики

Если модуль с заданным именем не найден в sys.modules, вызывается протокол импорта Python, чтобы найти и загрузить этот модуль. Протокол состоит из двух концептуальных объектов — поисковиков и загрузчиков. Задача поисковика — определить, может ли он найти модуль с заданным именем с помощью известной ему стратегии. Объекты, реализующие оба этих интерфейса, называются импортёрами: они возвращают сами себя, когда обнаруживают, что могут загрузить запрошенный модуль.

В Python есть несколько поисковиков и импортёров по умолчанию. Первый умеет находить встроенные модули, второй — замороженные. Третий поисковик по умолчанию ищет модули по пути импорта. Путь импорта — это список местоположений, которые могут указывать на пути файловой системы или zip-файлы. Его можно расширить так, чтобы поиск охватывал любой ресурс, местоположение которого можно определить, например ресурсы, заданные URL-адресами.

Механизм импорта можно дополнять: чтобы расширить диапазон и область поиска модулей, достаточно добавить новые поисковики.

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

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

Изменено в версии 3.4: В предыдущих версиях Python поисковики возвращали загрузчики напрямую, тогда как теперь они возвращают спецификации модулей, которые содержат загрузчики. Загрузчики по-прежнему используются при импорте, но у них стало меньше обязанностей.

5.3.3. Обработчики импорта

Механизм импорта спроектирован так, чтобы его можно было дополнять; главным способом для этого служат обработчики импорта. Существует два типа обработчиков импорта: метаобработчики и обработчики пути импорта.

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

Обработчики пути импорта вызываются как часть обработки sys.path (или package.__path__) в тот момент, когда встречается связанный с ними элемент пути. Обработчики пути импорта регистрируются добавлением новых вызываемых объектов в sys.path_hooks, как описано ниже.

5.3.4. Мета-путь

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

Если поисковик мета-пути умеет обрабатывать модуль с заданным именем, он возвращает объект спецификации. Если он не может обработать модуль, он возвращает None. Если обработка sys.meta_path доходит до конца списка и спецификация не возвращена, возбуждается исключение ModuleNotFoundError. Любые другие возбуждённые исключения просто передаются выше, прерывая процесс импорта.

Метод find_spec() поисковиков мета-пути вызывается с двумя или тремя аргументами. Первый — полное квалифицированное имя импортируемого модуля, например foo.bar.baz. Второй аргумент — элементы пути, используемые для поиска модуля. Для модулей верхнего уровня второй аргумент равен None, а для подмодулей или подпакетов — значению атрибута __path__ родительского пакета. Если нужный атрибут __path__ недоступен, возбуждается исключение ModuleNotFoundError. Третий аргумент — существующий объект модуля, который позднее станет целью загрузки. Система импорта передаёт целевой модуль только при перезагрузке.

Мета-путь может обходиться несколько раз для одного запроса на импорт. Например, если предположить, что ни один из задействованных модулей ещё не был кэширован, то импорт 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).

Некоторые поисковики мета-пути поддерживают только импорт верхнего уровня. Эти импортёры всегда возвращают None, если в качестве второго аргумента передано что-либо, кроме None.

В sys.meta_path по умолчанию в Python есть три поисковика мета-пути: один умеет импортировать встроенные модули, другой — замороженные, а третий — модули из пути импорта (то есть поисковик на основе пути).

Изменено в версии 3.4: Метод find_spec() поисковиков мета-пути заменил find_module(), который теперь объявлен устаревшим. Он продолжит работать без изменений, но механизм импорта будет пробовать его, только если поисковик не реализует find_spec().

Изменено в версии 3.10: Использование find_module() системой импорта теперь возбуждает ImportWarning.

Изменено в версии 3.12: Метод find_module() удалён. Вместо него используйте find_spec().

5.4. Loading

If and when a module spec is found, the import machinery will use it (and the loader it contains) when loading the module. Here is an approximation of what happens during the loading portion of import:

module = None
if spec.loader is not None and hasattr(spec.loader, 'create_module'):
    # It is assumed 'exec_module' will also be defined on the loader.
    module = spec.loader.create_module(spec)
if module is None:
    module = ModuleType(spec.name)
# The import-related module attributes get set here:
_init_module_attrs(spec, module)

if spec.loader is None:
    # unsupported
    raise ImportError

sys.modules[spec.name] = module
try:
    spec.loader.exec_module(module)
except BaseException:
    try:
        del sys.modules[spec.name]
    except KeyError:
        pass
    raise
return sys.modules[spec.name]

Note the following details:

  • If there is an existing module object with the given name in sys.modules, import will have already returned it.

  • The module will exist in sys.modules before the loader executes the module code. This is crucial because the module code may (directly or indirectly) import itself; adding it to sys.modules beforehand prevents unbounded recursion in the worst case and multiple loading in the best.

  • If loading fails, the failing module – and only the failing module – gets removed from sys.modules. Any module already in the sys.modules cache, and any module that was successfully loaded as a side-effect, must remain in the cache. This contrasts with reloading where even the failing module is left in sys.modules.

  • After the module is created but before execution, the import machinery sets the import-related module attributes («_init_module_attrs» in the pseudo-code example above), as summarized in a later section.

  • Module execution is the key moment of loading in which the module’s namespace gets populated. Execution is entirely delegated to the loader, which gets to decide what gets populated and how.

  • The module created during loading and passed to exec_module() may not be the one returned at the end of import [2].

Изменено в версии 3.4: The import system has taken over the boilerplate responsibilities of loaders. These were previously performed by the importlib.abc.Loader.load_module method.

Изменено в версии 3.15: The load_module method is no longer used.

5.4.1. Loaders

Module loaders provide the critical function of loading: module execution. The import machinery calls the importlib.abc.Loader.exec_module() method with a single argument, the module object to execute. Any value returned from exec_module() is ignored.

Loaders must satisfy the following requirements:

  • If the module is a Python module (as opposed to a built-in module or a dynamically loaded extension), the loader should execute the module’s code in the module’s global name space (module.__dict__).

  • If the loader cannot execute the module, it should raise an ImportError, although any other exception raised during exec_module() will be propagated.

In many cases, the finder and loader can be the same object; in such cases the find_spec() method would just return a spec with the loader set to self.

Module loaders may opt in to creating the module object during loading by implementing a create_module() method. It takes one argument, the module spec, and returns the new module object to use during loading. create_module() does not need to set any attributes on the module object. If the method returns None, the import machinery will create the new module itself.

Добавлено в версии 3.4: The create_module() method of loaders.

Изменено в версии 3.4: The importlib.abc.Loader.load_module method was replaced by exec_module() and the import machinery assumed all the boilerplate responsibilities of loading.

For compatibility with existing loaders, the import machinery will use the load_module() method of loaders if it exists and the loader does not also implement exec_module(). However, load_module() has been deprecated and loaders should implement exec_module() instead.

The load_module() method must implement all the boilerplate loading functionality described above in addition to executing the module. All the same constraints apply, with some additional clarification:

  • If there is an existing module object with the given name in sys.modules, the loader must use that existing module. (Otherwise, importlib.reload() will not work correctly.) If the named module does not exist in sys.modules, the loader must create a new module object and add it to sys.modules.

  • The module must exist in sys.modules before the loader executes the module code, to prevent unbounded recursion or multiple loading.

  • If loading fails, the loader must remove any modules it has inserted into sys.modules, but it must remove only the failing module(s), and only if the loader itself has loaded the module(s) explicitly.

Изменено в версии 3.5: A DeprecationWarning is raised when exec_module() is defined but create_module() is not.

Изменено в версии 3.6: An ImportError is raised when exec_module() is defined but create_module() is not.

Изменено в версии 3.10: Use of load_module() will raise ImportWarning.

5.4.2. Submodules

When a submodule is loaded using any mechanism (e.g. importlib APIs, the import or import-from statements, or built-in __import__()) a binding is placed in the parent module’s namespace to the submodule object. For example, if package spam has a submodule foo, after importing spam.foo, spam will have an attribute foo which is bound to the submodule. Let’s say you have the following directory structure:

spam/
    __init__.py
    foo.py

and spam/__init__.py has the following line in it:

from .foo import Foo

then executing the following puts name bindings for foo and Foo in the spam module:

>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.Foo
<class 'spam.foo.Foo'>

Given Python’s familiar name binding rules this might seem surprising, but it’s actually a fundamental feature of the import system. The invariant holding is that if you have sys.modules['spam'] and sys.modules['spam.foo'] (as you would after the above import), the latter must appear as the foo attribute of the former.

5.4.3. Module specs

The import machinery uses a variety of information about each module during import, especially before loading. Most of the information is common to all modules. The purpose of a module’s spec is to encapsulate this import-related information on a per-module basis.

Using a spec during import allows state to be transferred between import system components, e.g. between the finder that creates the module spec and the loader that executes it. Most importantly, it allows the import machinery to perform the boilerplate operations of loading, whereas without a module spec the loader had that responsibility.

The module’s spec is exposed as module.__spec__. Setting __spec__ appropriately applies equally to modules initialized during interpreter startup. The one exception is __main__, where __spec__ is set to None in some cases.

See ModuleSpec for details on the contents of the module spec.

Добавлено в версии 3.4.

5.4.4. __path__ attributes on modules

The __path__ attribute should be a (possibly empty) sequence of strings enumerating the locations where the package’s submodules will be found. By definition, if a module has a __path__ attribute, it is a package.

A package’s __path__ attribute is used during imports of its subpackages. Within the import machinery, it functions much the same as sys.path, i.e. providing a list of locations to search for modules during import. However, __path__ is typically much more constrained than sys.path.

The same rules used for sys.path also apply to a package’s __path__. sys.path_hooks (described below) are consulted when traversing a package’s __path__.

A package’s __init__.py file may set or alter the package’s __path__ attribute, and this was typically the way namespace packages were implemented prior to PEP 420. With the adoption of PEP 420, namespace packages no longer need to supply __init__.py files containing only __path__ manipulation code; the import machinery automatically sets __path__ correctly for the namespace package.

5.4.5. Module reprs

By default, all modules have a usable repr, however depending on the attributes set above, and in the module’s spec, you can more explicitly control the repr of module objects.

If the module has a spec (__spec__), the import machinery will try to generate a repr from it. If that fails or there is no spec, the import system will craft a default repr using whatever information is available on the module. It will try to use the module.__name__, module.__file__, and module.__loader__ as input into the repr, with defaults for whatever information is missing.

Here are the exact rules used:

  • If the module has a __spec__ attribute, the information in the spec is used to generate the repr. The «name», «loader», «origin», and «has_location» attributes are consulted.

  • If the module has a __file__ attribute, this is used as part of the module’s repr.

  • If the module has no __file__ but does have a __loader__ that is not None, then the loader’s repr is used as part of the module’s repr.

  • Otherwise, just use the module’s __name__ in the repr.

Изменено в версии 3.12: Use of module_repr(), having been deprecated since Python 3.4, was removed in Python 3.12 and is no longer called during the resolution of a module’s repr.

5.4.6. Cached bytecode invalidation

Before Python loads cached bytecode from a .pyc file, it checks whether the cache is up-to-date with the source .py file. By default, Python does this by storing the source’s last-modified timestamp and size in the cache file when writing it. At runtime, the import system then validates the cache file by checking the stored metadata in the cache file against the source’s metadata.

Python also supports «hash-based» cache files, which store a hash of the source file’s contents rather than its metadata. There are two variants of hash-based .pyc files: checked and unchecked. For checked hash-based .pyc files, Python validates the cache file by hashing the source file and comparing the resulting hash with the hash in the cache file. If a checked hash-based cache file is found to be invalid, Python regenerates it and writes a new checked hash-based cache file. For unchecked hash-based .pyc files, Python simply assumes the cache file is valid if it exists. Hash-based .pyc files validation behavior may be overridden with the --check-hash-based-pycs flag.

Изменено в версии 3.7: Added hash-based .pyc files. Previously, Python only supported timestamp-based invalidation of bytecode caches.

5.5. The Path Based Finder

As mentioned previously, Python comes with several default meta path finders. One of these, called the path based finder (PathFinder), searches an import path, which contains a list of path entries. Each path entry names a location to search for modules.

The path based finder itself doesn’t know how to import anything. Instead, it traverses the individual path entries, associating each of them with a path entry finder that knows how to handle that particular kind of path.

The default set of path entry finders implement all the semantics for finding modules on the file system, handling special file types such as Python source code (.py files), Python byte code (.pyc files) and shared libraries (e.g. .so files). When supported by the zipimport module in the standard library, the default path entry finders also handle loading all of these file types (other than shared libraries) from zipfiles.

Path entries need not be limited to file system locations. They can refer to URLs, database queries, or any other location that can be specified as a string.

The path based finder provides additional hooks and protocols so that you can extend and customize the types of searchable path entries. For example, if you wanted to support path entries as network URLs, you could write a hook that implements HTTP semantics to find modules on the web. This hook (a callable) would return a path entry finder supporting the protocol described below, which was then used to get a loader for the module from the web.

A word of warning: this section and the previous both use the term finder, distinguishing between them by using the terms meta path finder and path entry finder. These two types of finders are very similar, support similar protocols, and function in similar ways during the import process, but it’s important to keep in mind that they are subtly different. In particular, meta path finders operate at the beginning of the import process, as keyed off the sys.meta_path traversal.

By contrast, path entry finders are in a sense an implementation detail of the path based finder, and in fact, if the path based finder were to be removed from sys.meta_path, none of the path entry finder semantics would be invoked.

5.5.1. Path entry finders

The path based finder is responsible for finding and loading Python modules and packages whose location is specified with a string path entry. Most path entries name locations in the file system, but they need not be limited to this.

As a meta path finder, the path based finder implements the find_spec() protocol previously described, however it exposes additional hooks that can be used to customize how modules are found and loaded from the import path.

Three variables are used by the path based finder, sys.path, sys.path_hooks and sys.path_importer_cache. The __path__ attributes on package objects are also used. These provide additional ways that the import machinery can be customized.

sys.path contains a list of strings providing search locations for modules and packages. It is initialized from the PYTHONPATH environment variable and various other installation- and implementation-specific defaults. Entries in sys.path can name directories on the file system, zip files, and potentially other «locations» (see the site module) that should be searched for modules, such as URLs, or database queries. Only strings should be present on sys.path; all other data types are ignored.

The path based finder is a meta path finder, so the import machinery begins the import path search by calling the path based finder’s find_spec() method as described previously. When the path argument to find_spec() is given, it will be a list of string paths to traverse - typically a package’s __path__ attribute for an import within that package. If the path argument is None, this indicates a top level import and sys.path is used.

The path based finder iterates over every entry in the search path, and for each of these, looks for an appropriate path entry finder (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 (despite the name, this cache actually stores finder objects rather than being limited to importer objects). In this way, the expensive search for a particular 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.

If the path entry is not present in the cache, the path based finder iterates over every callable in sys.path_hooks. Each of the path entry hooks in this list is called with a single argument, the path entry to be searched. This callable may either return a path entry finder that can handle the path entry, or it may raise 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. The exception is ignored and 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.

If sys.path_hooks iteration ends with no path entry finder being returned, then the path based finder’s find_spec() method will store None in sys.path_importer_cache (to indicate that there is no finder for this path entry) and return None, indicating that this meta path finder could not find the module.

If a path entry finder is returned by one of the path entry hook callables on 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.

The current working directory – denoted by an empty string – is handled slightly differently from other entries on sys.path. First, if the current working directory cannot be determined or is found not to exist, no value is stored in sys.path_importer_cache. Second, the value for the current working directory is looked up fresh for each module lookup. Third, the path used for sys.path_importer_cache and returned by importlib.machinery.PathFinder.find_spec() will be the actual current working directory and not the empty string.

5.5.2. Path entry finder protocol

In order to support imports of modules and initialized packages and also to contribute portions to namespace packages, path entry finders must implement the find_spec() method.

find_spec() takes two arguments: the fully qualified name of the module being imported, and the (optional) target module. find_spec() returns a fully populated spec for the module. This spec will always have «loader» set (with one exception).

To indicate to the import machinery that the spec represents a namespace portion, the path entry finder sets submodule_search_locations to a list containing the portion.

Изменено в версии 3.4: find_spec() replaced find_loader() and find_module(), both of which are now deprecated, but will be used if find_spec() is not defined.

Older path entry finders may implement one of these two deprecated methods instead of find_spec(). The methods are still respected for the sake of backward compatibility. However, if find_spec() is implemented on the path entry finder, the legacy methods are ignored.

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.

For backwards compatibility with other implementations of the import protocol, many path entry finders also support the same, traditional find_module() method that meta path finders support. However path entry finder find_module() methods are never called with a path argument (they are expected to record the appropriate path information from the initial call to the path hook).

The find_module() method on path entry finders is deprecated, as it does not allow the path entry finder to contribute portions to namespace packages. If both find_loader() and find_module() exist on a path entry finder, the import system will always call find_loader() in preference to find_module().

Изменено в версии 3.10: Calls to find_module() and find_loader() by the import system will raise ImportWarning.

Изменено в версии 3.12: find_module() and find_loader() have been removed.

5.6. Replacing the standard import system

The most reliable mechanism for replacing the entire import system is to delete the default contents of sys.meta_path, replacing them entirely with a custom meta path hook.

If it is acceptable to only alter the behaviour of import statements without affecting other APIs that access the import system, then replacing the builtin __import__() function may be sufficient.

To selectively prevent the import of some modules from a hook early on the meta path (rather than disabling the standard import system entirely), it is sufficient to raise ModuleNotFoundError directly from find_spec() instead of returning None. The latter indicates that the meta path search should continue, while raising an exception terminates it immediately.

5.7. Package Relative Imports

Relative imports use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots indicate a relative import to the parent(s) of the current package, one level per dot after the first. For example, given the following package layout:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

In either subpackage1/moduleX.py or subpackage1/__init__.py, the following are valid relative imports:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo

Absolute imports may use either the import <> or from <> import <> syntax, but relative imports may only use the second form; the reason for this is that:

import XXX.YYY.ZZZ

should expose XXX.YYY.ZZZ as a usable expression, but .moduleY is not a valid expression.

5.8. Special considerations for __main__

The __main__ module is a special case relative to Python’s import system. As noted elsewhere, the __main__ module is directly initialized at interpreter startup, much like sys and 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.

5.8.1. __main__.__spec__

Depending on how __main__ is initialized, __main__.__spec__ gets set appropriately or to None.

When Python is started with the -m option, __spec__ is set to the module spec of the corresponding module or package. __spec__ is also populated when the __main__ module is loaded as part of executing a directory, zipfile or other sys.path entry.

In the remaining cases __main__.__spec__ is set to None, as the code used to populate the __main__ does not correspond directly with an importable module:

  • interactive prompt

  • -c option

  • running from stdin

  • running directly from a source or bytecode file

Note that __main__.__spec__ is always None in the last case, even if the file could technically be imported directly as a module instead. Use the -m switch if valid module metadata is desired in __main__.

Note also that even when __main__ corresponds with an importable module and __main__.__spec__ is set accordingly, they’re still considered distinct modules. This is due to the fact that blocks guarded by if __name__ == "__main__": checks only execute when the module is used to populate the __main__ namespace, and not during normal import.

5.9. References

The import machinery has evolved considerably since Python’s early days. The original specification for packages is still available to read, although some details have changed since the writing of that document.

The original specification for sys.meta_path was PEP 302, with subsequent extension in PEP 420.

PEP 420 introduced namespace packages for Python 3.3. PEP 420 also introduced the find_loader() protocol as an alternative to find_module().

PEP 366 describes the addition of the __package__ attribute for explicit relative imports in main modules.

PEP 328 introduced absolute and explicit relative imports and initially proposed __name__ for semantics PEP 366 would eventually specify for __package__.

PEP 338 defines executing modules as scripts.

PEP 451 adds the encapsulation of per-module import state in spec objects. It also off-loads most of the boilerplate responsibilities of loaders back onto the import machinery. These changes allow the deprecation of several APIs in the import system and also addition of new methods to finders and loaders.

Примечания