The Case for Laziness in Python 3.15


Some things take very little effort and save you a lot of time. Some things take a lot of time, and yet the payoff is minimal. I appreciate efficiency, but I have little patience for slackers. If you don’t care if something gets done well, I get it. But if your laziness means someone else has to do extra work, you are a slacker. Ever come home with takeout and found a sink full of dirty dishes? Some slacker made your life harder. Ever come home with takeout and a clean set of dishes in the dishrack? Life affirming. Don’t be a slacker.

We often carry import blocks from one project to the next, especially in environments where our code interacts with multiple scripts. You might be good at removing unused imports, but even your imports have dependencies. Or you might only import the specific function you need and delight in your own economy. Well, that doesn’t stop the full import from getting parsed. Python is eager; it drops everything to locate, parse, and execute that module immediately, making you pay for the dish setup before anyone sits down to eat.

Python 3.15 fixes this natively through PEP 810 and the lazy keyword.


Breaking the Namespace Illusion

The belief that from module import function only processes that function is a misconception. It limits what is visible in your namespace, but Python still evaluates the entire module behind the scenes. PEP 810 replaces this overhead by allowing explicit laziness at the module level:

lazy import numpy as np
lazy from scipy import stats

Instead of loading the library, Python creates a lightweight proxy. The actual parsing and resource consumption are paused until the exact millisecond your code invokes an attribute or method on that proxy. If your execution path bypasses the function using that library, it is never loaded.


Strict Boundaries and Trade-offs

To prevent runtime chaos, Python 3.15 enforces strict operational rules:

  • Module-Level Only: The lazy modifier is restricted to top-level scope. Using it inside a function triggers a SyntaxError.
  • No Wildcards: Syntax like lazy from module import * is banned; the runtime must know the bound names up front.
  • Global Controls: You can override behavior via the -X lazy_imports=<mode> flag or PYTHON_LAZY_IMPORTS env variable to force all imports to be lazy (all), respect the keywords (normal), or disable it entirely for debugging (none).

True efficiency means doing exactly the work required, but deferring execution shifts your errors. A missing or broken dependency will no longer fail cleanly at startup—it will fail deep within your runtime when first accessed. The lazy keyword is not a license to leave dead code around; it is a precision tool to keep your environment from doing unnecessary dishes behind your back.