Skip to content

Sample code for: Python 3.15 Preview: Lazy Imports - #808

Open
stephengruppetta wants to merge 2 commits into
masterfrom
python315-lazy-imports
Open

Sample code for: Python 3.15 Preview: Lazy Imports#808
stephengruppetta wants to merge 2 commits into
masterfrom
python315-lazy-imports

Conversation

@stephengruppetta

Copy link
Copy Markdown
Contributor

Sample code for the Real Python tutorial Python 3.15 Preview: Lazy Imports.

Standard library only, but it needs Python 3.15 — most files use the lazy keyword from PEP 810, which is a SyntaxError on anything earlier. Every file here was run against a CPython 3.15.0rc1 build, and the tutorial quotes its real output.

Layout

Path Section
noisy_module.py, probe.py Defer a Whole Module
shapes.py, partial.py Defer a Name From a Module
badfunc.py Find Out Where lazy Isn't Allowed
report_cli/ Speed Up a Real CLI
type_checking_guard.py, lazy_annotation.py Retire the if TYPE_CHECKING Dance
fail.py Read a Deferred Import Error
circular/ Don't Expect a Circular Import Fix
bridge.py, allmode.py Go Lazy Without the Keyword

report_cli/ holds three versions of the same CLI: cli_eager.py, cli_lazy.py (five lazy keywords, nothing else changed), and cli_too_lazy.py, which also defers the two plugin imports and so silently empties the format registry. bench.py times any of them, and a --load-all flag reads every deferred name so you can check that deferral costs nothing once the modules are used.

circular/ has four self-contained folders: eager/ fails, lazy/ is fixed by deferring one side, and init_eager/ + init_lazy/ both fail with the same ImportError because the cycle needs a value during module initialization.

One change outside the new folder

pyproject.toml adds python315-lazy-imports to ruff's exclude list. Two reasons:

  1. ruff 0.14.1 can't parse the lazy keyword. ruff format --check fails with invalid-syntax: Simple statements must be separated by newlines or semicolons on any file using it, which would break CI.
  2. With the folder excluded, the files can follow the Real Python style guide's blank-line rules — one blank line between definitions, not PEP 8's two — so the snippets in the tutorial and the files in this folder stay byte-identical.

CI passes locally with the exclusion in place: ruff format --check, ruff check, and dircheck.py are all green.

Stephen Gruppetta added 2 commits August 21, 2026 10:18
bench.py ignored the subprocess return code, so a script that crashed
was timed as if it had succeeded. A reader whose python isn't 3.15
would have seen cli_lazy.py die with a SyntaxError and bench.py report
it as a 2.5x speedup:

    $ python3.14 bench.py cli_lazy.py --help
    cli_lazy.py: 50 ms (best of 10)

That's the same silent, plausible-looking wrongness the tutorial warns
about in its own side-effects section. bench.py now checks the return
code, surfaces the captured stderr, and refuses to run at all below
3.15.

Also note in the README which files raise on purpose, and that a pyenv
build needs Tk headers or cli_eager.py won't start.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant