Issue #25802: Add an examples section to importlib.

Thanks to Berker Peksag for the patch review.
This commit is contained in:
Brett Cannon 2016-01-08 14:33:09 -08:00
parent fd65958f4f
commit a85e927e39
2 changed files with 99 additions and 7 deletions

View File

@ -81,7 +81,9 @@ This module provides an interface to the mechanisms used to implement the
.. deprecated:: 3.3
Use :func:`importlib.util.find_spec` instead unless Python 3.3
compatibility is required, in which case use
:func:`importlib.find_loader`.
:func:`importlib.find_loader`. For example usage of the former case,
see the :ref:`importlib-examples` section of the :mod:`importlib`
documentation.
.. function:: load_module(name, file, pathname, description)
@ -108,9 +110,12 @@ This module provides an interface to the mechanisms used to implement the
If previously used in conjunction with :func:`imp.find_module` then
consider using :func:`importlib.import_module`, otherwise use the loader
returned by the replacement you chose for :func:`imp.find_module`. If you
called :func:`imp.load_module` and related functions directly then use the
classes in :mod:`importlib.machinery`, e.g.
``importlib.machinery.SourceFileLoader(name, path).load_module()``.
called :func:`imp.load_module` and related functions directly with file
path arguments then use a combination of
:func:`importlib.util.spec_from_file_location` and
:func:`importlib.util.module_from_spec`. See the :ref:`importlib-examples`
section of the :mod:`importlib` documentation for details of the various
approaches.
.. function:: new_module(name)
@ -119,7 +124,7 @@ This module provides an interface to the mechanisms used to implement the
in ``sys.modules``.
.. deprecated:: 3.4
Use :class:`types.ModuleType` instead.
Use :func:`importlib.util.module_from_spec` instead.
.. function:: reload(module)

View File

@ -256,7 +256,7 @@ ABC hierarchy::
module and *path* will be the value of :attr:`__path__` from the
parent package. If a spec cannot be found, ``None`` is returned.
When passed in, ``target`` is a module object that the finder may
use to make a more educated about what spec to return.
use to make a more educated guess about what spec to return.
.. versionadded:: 3.4
@ -306,7 +306,7 @@ ABC hierarchy::
within the :term:`path entry` to which it is assigned. If a spec
cannot be found, ``None`` is returned. When passed in, ``target``
is a module object that the finder may use to make a more educated
about what spec to return.
guess about what spec to return.
.. versionadded:: 3.4
@ -1307,3 +1307,90 @@ an :term:`importer`.
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)])
.. _importlib-examples:
Examples
--------
To programmatically import a module, use :func:`importlib.import_module`.
::
import importlib
itertools = importlib.import_module('itertools')
If you need to find out if a module can be imported without actually doing the
import, then you should use :func:`importlib.util.find_spec`.
::
import importlib.util
import sys
# For illustrative purposes.
name = 'itertools'
spec = importlib.util.find_spec(name)
if spec is None:
print("can't find the itertools module")
else:
# If you chose to perform the actual import.
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Adding the module to sys.modules is optional.
sys.modules[name] = module
To import a Python source file directly, use the following recipe
(Python 3.4 and newer only)::
import importlib.util
import sys
# For illustrative purposes.
import tokenize
file_path = tokenize.__file__
module_name = tokenize.__name__
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Optional; only necessary if you want to be able to import the module
# by name later.
sys.modules[module_name] = module
Import itself is implemented in Python code, making it possible to
expose most of the import machinery through importlib. The following
helps illustrate the various APIs that importlib exposes by providing an
approximate implementation of
:func:`importlib.import_module` (Python 3.4 and newer for importlib usage,
Python 3.6 and newer for other parts of the code).
::
import importlib.util
import sys
def import_module(name, package=None):
"""An approximate implementation of import."""
absolute_name = importlib.util.resolve_name(name, package)
try:
return sys.modules[absolute_name]
except KeyError:
pass
path = None
if '.' in absolute_name:
parent_name, _, child_name = absolute_name.rpartition('.')
parent_module = import_module(parent_name)
path = parent_module.spec.submodule_search_locations
for finder in sys.meta_path:
spec = finder.find_spec(absolute_name, path)
if spec is not None:
break
else:
raise ImportError(f'No module named {absolute_name!r}')
module = spec.loader.create_module(spec)
spec.loader.exec_module(module)
sys.modules[absolute_name] = module
if path is not None:
setattr(parent_module, child_name, module)
return module