Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions peps/pep-0810.rst
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ The overhead is minimal:
the slow path away.
- Small one-time cost to create the proxy object.
- Reification (first use) has the same cost as a regular import.
- No ongoing performance penalty unlike ``importlib.util.LazyLoader``.
- No ongoing performance penalty.

Benchmarking with the `pyperformance suite`_ shows the implementation is
performance neutral when lazy imports are not used.
Expand Down Expand Up @@ -1048,7 +1048,6 @@ Why not use ``importlib.util.LazyLoader`` instead?
``LazyLoader`` has significant limitations:

- Requires verbose setup code for each lazy import.
- Has ongoing performance overhead on every attribute access.
- Doesn't work well with ``from ... import`` statements.
- Less clear and standard than dedicated syntax.

Expand Down Expand Up @@ -1283,6 +1282,13 @@ any eager import.

print('json' in sys.modules) # True

Does ``lazy from __future__ import feature`` work?
--------------------------------------------------

No, future imports can't be lazy because they're parser/compiler directives.
It's technically possible for the runtime behavior to be lazy but there's no
real value in it.

Why you chose ``lazy`` as the keyword name?
-------------------------------------------

Expand Down Expand Up @@ -1319,6 +1325,14 @@ imports. The most compelling alternates were ``defer`` and ``delay``.
Rejected Ideas
==============

Making the new behavior the default
-----------------------------------

Changing ``import`` to be lazy by default is outside of the scope of this PEP.
From the discussion on :pep:`690` it is clear that this is a fairly
contentious idea, although perhaps once we have wide-spread use of lazy
imports this can be reconsidered.

Modification of the dict object
-------------------------------

Expand Down Expand Up @@ -1346,6 +1360,24 @@ Past decisions that violated this principle of keeping core abstractions clean
have caused significant pain in the CPython ecosystem, making optimization
difficult and introducing subtle bugs.

Making ``lazy`` imports find the module without loading it
----------------------------------------------------------

The Python ``import`` machinery separates out finding a module and loading
it, and the lazy import implementation could technically defer only the
loading part. However:

- Finding the module does not guarantee the import will succeed, nor even
that it will not raise ImportError.
- Finding modules in packages requires that those packages are loaded, so
it would only help with lazy loading one level of a package hierarchy.
- Since "finding" attributes in modules *requires* loading them, this would
create a hard to explain difference between
``from package import module`` and ``from module import function``.
- A significant part of the performance win is skipping the finding part
(which may involve filesystem searches and consulting multiple importers
and meta-importers).

Placing the ``lazy`` keyword in the middle of from imports
----------------------------------------------------------

Expand All @@ -1364,6 +1396,37 @@ this approach provided less clarity. For example, if multiple modules are
imported in a single statement, it is unclear if the lazy binding applies to
all of the imported objects or just a subset of the items.

Adding an explicit ``eager`` keyword
------------------------------------

Since we're not changing the default behavior, and we don't want to
encourage use of the global flags, it's too early to consider adding
superfluous syntax for the common, default case. It would create too much
confusion about what the default is, or when the ``eager`` keyword would be
necessary, or whether it affects lazy imports *in* the explicitly eagerly
imported module.

Using a context manager instead of a new soft keyword
-----------------------------------------------------

A backward compatible syntax, for example in the form of a context manager,
has been proposed:

.. code-block:: python

with lazy_imports(...):
import json

This would replace the need for :data:`!__lazy_modules__`, and allow
libraries to use one of the existing lazy imports implementations in older
Python versions. However, adding magic ``with`` statements with that kind of
effect would be a signficant change to Python and ``with`` statements in
general, and it would not be easy to combine with the implementation for
lazy imports in this proposal. Adding standard library support for existing
lazy importers *without* changes to the implementation amounts to the status
quo, and does not solve the performance and usability issues with those
existing solutions.

Returning a proxy dict from ``globals()``
------------------------------------------

Expand Down