My Python colleagues are about to get something we stopped noticing around PHP 5.3: code that loads only when you touch it. Python 3.15 lands on October 1 carrying PEP 810, explicit lazy imports, and reading the spec felt like flipping through Composer's baby photos. So let me stake my claim right away: the new keyword will be fine, the global switch will hurt someone, and the difference between the two comes down to a rule our ecosystem internalized so long ago we forgot it was ever a rule.
python -X importtime -c "import pandas"Mechanics first. The steering council accepted PEP 810 unanimously on November 3, 2025, four votes with co-author Pablo Galindo Salgado sitting out, and release candidate 2 shipped on September 1. You write lazy import pandas or lazy from json import dumps, the name receives a placeholder, and Python performs the real import only when that placeholder is first used. Any PHP developer recognizes the shape on sight. It is spl_autoload_register wearing a soft keyword.
Here is why autoloading never bit us the way it theoretically could have. PSR-4 came bundled with an unwritten companion rule: a file that defines a class does nothing else. No side effects, just a declaration. Such a file can be loaded now or in ten minutes and the program cannot tell the difference. Python modules are the opposite by design. Importing one executes it top to bottom, and mature libraries lean on that moment for plugin registration and monkey-patching. Defer those loads and you have reordered side effects across the entire process.
PEP 810's authors clearly understand this, which is why the keyword is fenced in hard: module level only, forbidden inside functions, class bodies, try blocks, and import *. The try-block ban stings the most, because it rules out the classic optional-dependency dance where you attempt to import pyarrow, catch ImportError, and fall back to a None sentinel. Under deferral the failure would surface at first use, long after the surrounding except clause finished doing nothing, so the ban is honest engineering. The consolation prizes are decent too: when a deferred import blows up, the exception chain points back to the declaration site as well as the access that triggered it, and a failed load gets retried on the next touch.
About the promised wins, keep your skepticism warm. The PEP cites startup reductions of 50 to 70 percent and memory savings of 30 to 40 percent without pinning either figure to a named codebase; the one attributed case, Christian Tismer's PySide work, lands at 10 to 20 percent. Meta's Instagram and Hudson River Trading are name-checked as production users, no numbers attached. The raw material is real enough. On CPython 3.11 a warm import pandas costs roughly 250 milliseconds, NumPy alone about 64, and an empty interpreter gets going in under 3. Whether a quarter second matters depends entirely on how long the process lives. In a CLI someone runs all day, it matters a lot. In a worker that boots once and chews a queue for a week, it vanishes, for the same reason Laravel Octane makes framework boot cost irrelevant by paying it exactly once.
Now the part that deserves a change-review ticket. PEP 810 ships three modes, normal, all, and none, settable through sys.set_lazy_imports(), the -X lazy_imports flag, or the PYTHON_LAZY_IMPORTS environment variable, plus a filter hook in sys.set_lazy_imports_filter() and a sys.lazy_modules set tracking names that have not materialized yet. Mode all defers every import in the process, including those inside dependencies whose maintainers never tested deferral and in some cases rely outright on import-time execution. The PEP tells those maintainers the fix: stop doing registration work at import time, expose an explicit init function instead. That is precisely the discipline PHP needed years and a package manager to make universal, and Python is requesting it retroactively while handing every ops team a single variable that assumes the work is already done.
So here is where I land, after conceding the genuinely good parts. The opt-in keyword is well designed, and marking the heavy imports at the top of a CLI entry point, then checking the delta with -X importtime, is free money you should collect. But treat mode all the way you would treat swapping out the autoloader in a live shop, and keep it far from any job that writes data. An eager import that fails kills the process before any work starts, a clean restart. A deferred one can fail after rows have already gone out the door, and no cold-start graph justifies inheriting that cleanup.
Which brings me to you. Imagine we got the mirror image tomorrow: one env var that made every require in vendor/ lazy, side effects be damned. Would you flip it on a production box for a faster boot? If your answer is no, I want to hear what evidence would change your mind, because somewhere in your company a Python team is about to place exactly that bet.




Comments
No comments yet — be the first.
Open the discussion
No account or password needed — just enter your e-mail and we’ll send you a one-time sign-in link. First time here? You’re set up automatically.
Your rating will be applied automatically after you sign in.
Check your inbox
We’ve sent a sign-in link to …. Open it on this device — this tab will sign you in automatically.
Nothing arrived? Check your spam folder — and mark the mail as "Not spam" so it lands in your inbox next time.