Kaydet (Commit) 7cff4cd7 authored tarafından Eric Snow's avatar Eric Snow

Issue #19713: Fix mistakes in the import page of language reference.

These mistakes were introduced by the initial PEP 451 merge.
üst ca2d854d
...@@ -281,9 +281,10 @@ When the named module is not found in :data:`sys.modules`, Python next ...@@ -281,9 +281,10 @@ When the named module is not found in :data:`sys.modules`, Python next
searches :data:`sys.meta_path`, which contains a list of meta path finder searches :data:`sys.meta_path`, which contains a list of meta path finder
objects. These finders are queried in order to see if they know how to handle objects. These finders are queried in order to see if they know how to handle
the named module. Meta path finders must implement a method called the named module. Meta path finders must implement a method called
:meth:`find_spec()` which takes two arguments, a name and an import path. :meth:`~importlib.abc.MetaPathFinder.find_spec()` which takes three arguments:
The meta path finder can use any strategy it wants to determine whether it can a name, an import path, and (optionally) a target module. The meta path
handle the named module or not. finder can use any strategy it wants to determine whether it can handle
the named module or not.
If the meta path finder knows how to handle the named module, it returns a If the meta path finder knows how to handle the named module, it returns a
spec object. If it cannot handle the named module, it returns ``None``. If spec object. If it cannot handle the named module, it returns ``None``. If
...@@ -291,24 +292,26 @@ spec object. If it cannot handle the named module, it returns ``None``. If ...@@ -291,24 +292,26 @@ spec object. If it cannot handle the named module, it returns ``None``. If
a spec, then an :exc:`ImportError` is raised. Any other exceptions raised a spec, then an :exc:`ImportError` is raised. Any other exceptions raised
are simply propagated up, aborting the import process. are simply propagated up, aborting the import process.
The :meth:`find_spec()` method of meta path finders is called with two The :meth:`~importlib.abc.MetaPathFinder.find_spec()` method of meta path
arguments. The first is the fully qualified name of the module being finders is called with two or three arguments. The first is the fully
imported, for example ``foo.bar.baz``. The second argument is the path qualified name of the module being imported, for example ``foo.bar.baz``.
entries to use for the module search. For top-level modules, the second The second argument is the path entries to use for the module search. For
argument is ``None``, but for submodules or subpackages, the second top-level modules, the second argument is ``None``, but for submodules or
argument is the value of the parent package's ``__path__`` attribute. If subpackages, the second argument is the value of the parent package's
the appropriate ``__path__`` attribute cannot be accessed, an ``__path__`` attribute. If the appropriate ``__path__`` attribute cannot
:exc:`ImportError` is raised. be accessed, an :exc:`ImportError` is raised. The third argument is an
existing module object that will be the target of loading later. The
import system passes in a target module only during reload.
The meta path may be traversed multiple times for a single import request. The meta path may be traversed multiple times for a single import request.
For example, assuming none of the modules involved has already been cached, For example, assuming none of the modules involved has already been cached,
importing ``foo.bar.baz`` will first perform a top level import, calling importing ``foo.bar.baz`` will first perform a top level import, calling
``mpf.find_spec("foo", None)`` on each meta path finder (``mpf``). After ``mpf.find_spec("foo", None, None)`` on each meta path finder (``mpf``). After
``foo`` has been imported, ``foo.bar`` will be imported by traversing the ``foo`` has been imported, ``foo.bar`` will be imported by traversing the
meta path a second time, calling meta path a second time, calling
``mpf.find_spec("foo.bar", foo.__path__)``. Once ``foo.bar`` has been ``mpf.find_spec("foo.bar", foo.__path__, None)``. Once ``foo.bar`` has been
imported, the final traversal will call imported, the final traversal will call
``mpf.find_spec("foo.bar.baz", foo.bar.__path__)``. ``mpf.find_spec("foo.bar.baz", foo.bar.__path__, None)``.
Some meta path finders only support top level imports. These importers will Some meta path finders only support top level imports. These importers will
always return ``None`` when anything other than ``None`` is passed as the always return ``None`` when anything other than ``None`` is passed as the
...@@ -320,10 +323,11 @@ modules, and one that knows how to import modules from an :term:`import path` ...@@ -320,10 +323,11 @@ modules, and one that knows how to import modules from an :term:`import path`
(i.e. the :term:`path based finder`). (i.e. the :term:`path based finder`).
.. versionchanged:: 3.4 .. versionchanged:: 3.4
The find_spec() method of meta path finders replaced :meth:`find_module()`. The :meth:`~importlib.abc.MetaPathFinder.find_spec` method of meta path
which is now deprecated. While it will continue to work without change, finders replaced :meth:`~importlib.abc.MetaPathFinder.find_module`, which
the import machinery will try it only if the finder does not implement is now deprecated. While it will continue to work without change, the
find_spec(). import machinery will try it only if the finder does not implement
``find_spec()``.
Loading Loading
...@@ -350,6 +354,7 @@ of what happens during the loading portion of import:: ...@@ -350,6 +354,7 @@ of what happens during the loading portion of import::
raise ImportError raise ImportError
elif not hasattr(spec.loader, 'exec_module'): elif not hasattr(spec.loader, 'exec_module'):
module = spec.loader.load_module(spec.name) module = spec.loader.load_module(spec.name)
# Set __loader__ and __package__ if missing.
else: else:
sys.modules[spec.name] = module sys.modules[spec.name] = module
try: try:
...@@ -360,7 +365,7 @@ of what happens during the loading portion of import:: ...@@ -360,7 +365,7 @@ of what happens during the loading portion of import::
except KeyError: except KeyError:
pass pass
raise raise
module_to_return = sys.modules[spec.name] return sys.modules[spec.name]
Note the following details: Note the following details:
...@@ -380,8 +385,9 @@ Note the following details: ...@@ -380,8 +385,9 @@ Note the following details:
reloading where even the failing module is left in :data:`sys.modules`. reloading where even the failing module is left in :data:`sys.modules`.
* After the module is created but before execution, the import machinery * After the module is created but before execution, the import machinery
sets the import-related module attributes ("init_module_attrs"), as sets the import-related module attributes ("_init_module_attrs" in
summarized in a :ref:`later section <import-mod-attrs>`. the pseudo-code example above), as summarized in a
:ref:`later section <import-mod-attrs>`.
* Module execution is the key moment of loading in which the module's * Module execution is the key moment of loading in which the module's
namespace gets populated. Execution is entirely delegated to the namespace gets populated. Execution is entirely delegated to the
...@@ -392,16 +398,16 @@ Note the following details: ...@@ -392,16 +398,16 @@ Note the following details:
.. versionchanged:: 3.4 .. versionchanged:: 3.4
The import system has taken over the boilerplate responsibilities of The import system has taken over the boilerplate responsibilities of
loaders. These were previously performed by the :meth:`load_module()` loaders. These were previously performed by the
method. :meth:`importlib.abc.Loader.load_module` method.
Loaders Loaders
------- -------
Module loaders provide the critical function of loading: module execution. Module loaders provide the critical function of loading: module execution.
The import machinery calls the :meth:`~importlib.abc.Loader.exec_module()` The import machinery calls the :meth:`importlib.abc.Loader.exec_module`
method with a single argument, the module object to execute. Any value method with a single argument, the module object to execute. Any value
returned from exec_module() is ignored. returned from :meth:`~importlib.abc.Loader.exec_module` is ignored.
Loaders must satisfy the following requirements: Loaders must satisfy the following requirements:
...@@ -409,41 +415,41 @@ Loaders must satisfy the following requirements: ...@@ -409,41 +415,41 @@ Loaders must satisfy the following requirements:
dynamically loaded extension), the loader should execute the module's code dynamically loaded extension), the loader should execute the module's code
in the module's global name space (``module.__dict__``). in the module's global name space (``module.__dict__``).
* If loader cannot execute the module, it should raise an * If the loader cannot execute the module, it should raise an
:exc:`ImportError`, although any other exception raised during :exc:`ImportError`, although any other exception raised during
:meth:`exec_module()` will be propagated. :meth:`~importlib.abc.Loader.exec_module` will be propagated.
In many cases, the finder and loader can be the same object; in such cases the In many cases, the finder and loader can be the same object; in such cases the
:meth:`finder.find_spec()` would just return a spec with the loader set :meth:`~importlib.abc.MetaPathFinder.find_spec` method would just return a
to ``self``. spec with the loader set to ``self``.
Module loaders may opt in to creating the module object during loading Module loaders may opt in to creating the module object during loading
by implementing a :meth:`create_module()` method. It takes one argument, by implementing a :meth:`~importlib.abc.Loader.create_module` method.
the module spec, and returns the new module object to use during loading. It takes one argument, the module spec, and returns the new module object
create_module() does not need to set any attributes on the module object. to use during loading. ``create_module()`` does not need to set any attributes
If the loader does not define create_module(), the import machinery will on the module object. If the loader does not define ``create_module()``, the
create the new module itself. import machinery will create the new module itself.
.. versionadded:: 3.4 .. versionadded:: 3.4
The create_module() method of loaders. The create_module() method of loaders.
.. versionchanged:: 3.4 .. versionchanged:: 3.4
The load_module() method was replaced by exec_module() and the import The :meth:`~importlib.abc.Loader.load_module` method was replaced by
:meth:`~importlib.abc.Loader.exec_module` and the import
machinery assumed all the boilerplate responsibilities of loading. machinery assumed all the boilerplate responsibilities of loading.
For compatibility with existing loaders, the import machinery will use For compatibility with existing loaders, the import machinery will use
the :meth:`~importlib.abc.Loader.load_module()` method of loaders if it the ``load_module()`` method of loaders if it exists and the loader does
exists and the loader does not also implement exec_module(). However, not also implement ``exec_module(). However, ``load_module()`` has been
load_module() has been deprecated and loaders should implement deprecated and loaders should implement ``exec_module()`` instead.
exec_module() instead.
The load_module() method must implement all the boilerplate loading The ``load_module()`` method must implement all the boilerplate loading
functionality described above in addition to executing the module. All functionality described above in addition to executing the module. All
the same constraints apply, with some additional clarification: the same constraints apply, with some additional clarification:
* If there is an existing module object with the given name in * If there is an existing module object with the given name in
:data:`sys.modules`, the loader must use that existing module. :data:`sys.modules`, the loader must use that existing module.
(Otherwise, :func:`imp.reload` will not work correctly.) If the (Otherwise, :func:`importlib.reload` will not work correctly.) If the
named module does not exist in :data:`sys.modules`, the loader named module does not exist in :data:`sys.modules`, the loader
must create a new module object and add it to :data:`sys.modules`. must create a new module object and add it to :data:`sys.modules`.
...@@ -515,6 +521,8 @@ the module. ...@@ -515,6 +521,8 @@ the module.
used when importing the module. This is used primarily for used when importing the module. This is used primarily for
introspection and during reloading. introspection and during reloading.
.. versionadded:: 3.4
.. attribute:: __path__ .. attribute:: __path__
If the module is a package (either regular or namespace), the module If the module is a package (either regular or namespace), the module
...@@ -600,13 +608,14 @@ Here are the exact rules used: ...@@ -600,13 +608,14 @@ Here are the exact rules used:
* Otherwise, just use the module's ``__name__`` in the repr. * Otherwise, just use the module's ``__name__`` in the repr.
.. versionchanged:: 3.4 .. versionchanged:: 3.4
Use of loader.module_repr() has been deprecated and the module spec Use of :meth:`loader.module_repr() <importlib.abc.Loader.module_repr>`
is now used by the import machinery to generate a module repr. has been deprecated and the module spec is now used by the import
machinery to generate a module repr.
For backward compatibility with Python 3.3, the module repr will be For backward compatibility with Python 3.3, the module repr will be
generated by calling the loader's :meth:`module_repr()` method, if generated by calling the loader's
defined, before trying either approach described above. However, the :meth:`~importlib.abc.Loader.module_repr` method, if defined, before
method is deprecated. trying either approach described above. However, the method is deprecated.
The Path Based Finder The Path Based Finder
...@@ -616,8 +625,9 @@ The Path Based Finder ...@@ -616,8 +625,9 @@ The Path Based Finder
single: path based finder single: path based finder
As mentioned previously, Python comes with several default meta path finders. As mentioned previously, Python comes with several default meta path finders.
One of these, called the :term:`path based finder`, searches an :term:`import One of these, called the :term:`path based finder`
path`, which contains a list of :term:`path entries <path entry>`. Each path (:class:`~importlib.machinery.PathFinder`) , searches an :term:`import path`,
which contains a list of :term:`path entries <path entry>`. Each path
entry names a location to search for modules. entry names a location to search for modules.
The path based finder itself doesn't know how to import anything. Instead, it The path based finder itself doesn't know how to import anything. Instead, it
...@@ -666,15 +676,15 @@ Path entry finders ...@@ -666,15 +676,15 @@ Path entry finders
single: sys.path_importer_cache single: sys.path_importer_cache
single: PYTHONPATH single: PYTHONPATH
The :term:`path based finder` is responsible for finding and loading Python The :term:`path based finder` is responsible for finding and loading
modules and packages whose location is specified with a string :term:`path Python modules and packages whose location is specified with a string
entry`. Most path entries name locations in the file system, but they need :term:`path entry`. Most path entries name locations in the file system,
not be limited to this. but they need not be limited to this.
As a meta path finder, the :term:`path based finder` implements the As a meta path finder, the :term:`path based finder` implements the
:meth:`find_spec()` protocol previously described, however it exposes :meth:`~importlib.abc.MetaPathFinder.find_spec` protocol previously
additional hooks that can be used to customize how modules are found and described, however it exposes additional hooks that can be used to
loaded from the :term:`import path`. customize how modules are found and loaded from the :term:`import path`.
Three variables are used by the :term:`path based finder`, :data:`sys.path`, Three variables are used by the :term:`path based finder`, :data:`sys.path`,
:data:`sys.path_hooks` and :data:`sys.path_importer_cache`. The ``__path__`` :data:`sys.path_hooks` and :data:`sys.path_importer_cache`. The ``__path__``
...@@ -694,14 +704,16 @@ finder>`. ...@@ -694,14 +704,16 @@ finder>`.
The :term:`path based finder` is a :term:`meta path finder`, so the import The :term:`path based finder` is a :term:`meta path finder`, so the import
machinery begins the :term:`import path` search by calling the path machinery begins the :term:`import path` search by calling the path
based finder's :meth:`find_spec()` method as described previously. When based finder's :meth:`~importlib.machinery.PathFinder.find_spec` method as
the ``path`` argument to :meth:`find_spec()` is given, it will be a described previously. When the ``path`` argument to
:meth:`~importlib.machinery.PathFinder.find_spec` is given, it will be a
list of string paths to traverse - typically a package's ``__path__`` list of string paths to traverse - typically a package's ``__path__``
attribute for an import within that package. If the ``path`` argument attribute for an import within that package. If the ``path`` argument is
is ``None``, this indicates a top level import and :data:`sys.path` is used. ``None``, this indicates a top level import and :data:`sys.path` is used.
The path based finder iterates over every entry in the search path, and The path based finder iterates over every entry in the search path, and
for each of these, looks for an appropriate :term:`path entry finder` for the for each of these, looks for an appropriate :term:`path entry finder`
(:class:`~importlib.abc.PathEntryFinder`) for the
path entry. Because this can be an expensive operation (e.g. there may be 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 `stat()` call overheads for this search), the path based finder maintains
a cache mapping path entries to path entry finders. This cache is maintained a cache mapping path entries to path entry finders. This cache is maintained
...@@ -718,18 +730,20 @@ hooks <path entry hook>` in this list is called with a single argument, the ...@@ -718,18 +730,20 @@ hooks <path entry hook>` in this list is called with a single argument, the
path entry to be searched. This callable may either return a :term:`path path entry to be searched. This callable may either return a :term:`path
entry finder` that can handle the path entry, or it may raise entry finder` that can handle the path entry, or it may raise
:exc:`ImportError`. An :exc:`ImportError` is used by the path based finder to :exc:`ImportError`. An :exc:`ImportError` is used by the path based finder to
signal that the hook cannot find a :term:`path entry finder` for that signal that the hook cannot find a :term:`path entry finder`.
:term:`path entry`. The exception is ignored and :term:`import path` for that :term:`path entry`. The
iteration continues. The hook should expect either a string or bytes object; exception is ignored and :term:`import path` iteration continues. The hook
the encoding of bytes objects is up to the hook (e.g. it may be a file system should expect either a string or bytes object; the encoding of bytes objects
encoding, UTF-8, or something else), and if the hook cannot decode the is up to the hook (e.g. it may be a file system encoding, UTF-8, or something
argument, it should raise :exc:`ImportError`. else), and if the hook cannot decode the argument, it should raise
:exc:`ImportError`.
If :data:`sys.path_hooks` iteration ends with no :term:`path entry finder` If :data:`sys.path_hooks` iteration ends with no :term:`path entry finder`
being returned, then the path based finder's :meth:`find_spec()` method being returned, then the path based finder's
will store ``None`` in :data:`sys.path_importer_cache` (to indicate that :meth:`~importlib.machinery.PathFinder.find_spec` method will store ``None``
there is no finder for this path entry) and return ``None``, indicating that in :data:`sys.path_importer_cache` (to indicate that there is no finder for
this :term:`meta path finder` could not find the module. this path entry) and return ``None``, indicating that this
:term:`meta path finder` could not find the module.
If a :term:`path entry finder` *is* returned by one of the :term:`path entry If a :term:`path entry finder` *is* returned by one of the :term:`path entry
hook` callables on :data:`sys.path_hooks`, then the following protocol is used hook` callables on :data:`sys.path_hooks`, then the following protocol is used
...@@ -741,12 +755,12 @@ Path entry finder protocol ...@@ -741,12 +755,12 @@ Path entry finder protocol
In order to support imports of modules and initialized packages and also to In order to support imports of modules and initialized packages and also to
contribute portions to namespace packages, path entry finders must implement contribute portions to namespace packages, path entry finders must implement
the :meth:`find_spec()` method. the :meth:`~importlib.abc.PathEntryFinder.find_spec` method.
:meth:`find_spec()` takes one argument, the fully qualified name of the :meth:`~importlib.abc.PathEntryFinder.find_spec` takes two argument, the
module being imported. :meth:`find_spec()` returns a fully populated fully qualified name of the module being imported, and the (optional) target
spec for the module. This spec will always have "loader" set (with one module. ``find_spec()`` returns a fully populated spec for the module.
exception). This spec will always have "loader" set (with one exception).
To indicate to the import machinery that the spec represents a namespace To indicate to the import machinery that the spec represents a namespace
:term:`portion`. the path entry finder sets "loader" on the spec to :term:`portion`. the path entry finder sets "loader" on the spec to
...@@ -754,42 +768,44 @@ To indicate to the import machinery that the spec represents a namespace ...@@ -754,42 +768,44 @@ To indicate to the import machinery that the spec represents a namespace
portion. portion.
.. versionchanged:: 3.4 .. versionchanged:: 3.4
find_spec() replaced find_loader() and find_module(), but of which :meth:`~importlib.abc.PathEntryFinder.find_spec` replaced
are now deprecated, but will be used if find_spec() is not defined. :meth:`~importlib.abc.PathEntryFinder.find_loader` and
:meth:`~importlib.abc.PathEntryFinder.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 Older path entry finders may implement one of these two deprecated methods
instead of :meth:`find_spec()`. The methods are still respected for the instead of ``find_spec()``. The methods are still respected for the
sake of backward compatibility. Howevever, if find_spec() is implemented sake of backward compatibility. Howevever, if ``find_spec()`` is
on the path entry finder, the legacy methods are ignored. implemented on the path entry finder, the legacy methods are ignored.
:meth:`find_loader()` takes one argument, the fully qualified name of the :meth:`~importlib.abc.PathEntryFinder.find_loader` takes one argument, the
module being imported. :meth:`find_loader()` returns a 2-tuple where the fully qualified name of the module being imported. ``find_loader()``
first item is the loader and the second item is a namespace :term:`portion`. returns a 2-tuple where the first item is the loader and the second item
When the first item (i.e. the loader) is ``None``, this means that while the is a namespace :term:`portion`. When the first item (i.e. the loader) is
path entry finder does not have a loader for the named module, it knows that ``None``, this means that while the path entry finder does not have a
the path entry contributes to a namespace portion for the named module. loader for the named module, it knows that the path entry contributes to
This will almost always be the case where Python is asked to import a a namespace portion for the named module. This will almost always be the
namespace package that has no physical presence on the file system. case where Python is asked to import a namespace package that has no
When a path entry finder returns ``None`` for the loader, the second physical presence on the file system. When a path entry finder returns
item of the 2-tuple return value must be a sequence, although it can be ``None`` for the loader, the second item of the 2-tuple return value must
empty. be a sequence, although it can be empty.
If :meth:`find_loader()` returns a non-``None`` loader value, the portion is If ``find_loader()`` returns a non-``None`` loader value, the portion is
ignored and the loader is returned from the path based finder, terminating ignored and the loader is returned from the path based finder, terminating
the search through the path entries. the search through the path entries.
For backwards compatibility with other implementations of the import For backwards compatibility with other implementations of the import
protocol, many path entry finders also support the same, protocol, many path entry finders also support the same,
traditional :meth:`find_module()` method that meta path finders support. traditional ``find_module()`` method that meta path finders support.
However path entry finder :meth:`find_module()` methods are never called However path entry finder ``find_module()`` methods are never called
with a ``path`` argument (they are expected to record the appropriate with a ``path`` argument (they are expected to record the appropriate
path information from the initial call to the path hook). path information from the initial call to the path hook).
The :meth:`find_module()` method on path entry finders is deprecated, The ``find_module()`` method on path entry finders is deprecated,
as it does not allow the path entry finder to contribute portions to as it does not allow the path entry finder to contribute portions to
namespace packages. If both :meth:`find_loader()` and :meth:`find_module()` namespace packages. If both ``find_loader()`` and ``find_module()``
exist on a path entry finder, the import system will always call exist on a path entry finder, the import system will always call
:meth:`find_loader()` in preference to :meth:`find_module()`. ``find_loader()`` in preference to ``find_module()``.
Replacing the standard import system Replacing the standard import system
...@@ -808,9 +824,9 @@ import statements within that module. ...@@ -808,9 +824,9 @@ import statements within that module.
To selectively prevent import of some modules from a hook early on the To selectively prevent import of some modules from a hook early on the
meta path (rather than disabling the standard import system entirely), meta path (rather than disabling the standard import system entirely),
it is sufficient to raise :exc:`ImportError` directly from it is sufficient to raise :exc:`ImportError` directly from
:meth:`find_spec` instead of returning ``None``. The latter indicates :meth:`~importlib.abc.MetaPathFinder.find_spec` instead of returning
that the meta path search should continue. while raising an exception ``None``. The latter indicates that the meta path search should continue,
terminates it immediately. while raising an exception terminates it immediately.
Open issues Open issues
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment