Python 3.15 adds lazy imports: a lazy keyword that puts off loading a module until the first time you use it. The import statement stays where it belongs, at the top of your file, but the work of running it moves to the moment something touches the module’s name. In this tutorial, you’ll make a command-line tool start more than twice as fast without moving a single import.
By the end of this tutorial, you’ll understand that:
- A lazy import binds its name immediately and loads the module the first time something reads that name.
- Deferring the imports that a code path never touches can cut startup time sharply, and every import still sits at the top of the file.
lazyis rejected inside functions, class bodies, andtryblocks, so a deferred import can’t slip past anexcept ImportErrorfallback.__lazy_modules__lets one file defer on Python 3.15 and stay eager on older versions because they ignore it silently instead of refusing to parse it.- A module that does its work at import time, such as registering a plugin, never runs at all if nothing reads its name.
First, you’ll install a Python 3.15 pre-release. Then you’ll measure what your imports cost today, see why the old workarounds are unsatisfying, write your first lazy import, and put the keyword to work on a real command-line tool. Along the way, you’ll retire the if TYPE_CHECKING guard, run into the imports that have to stay eager, and learn how to adopt deferral in a codebase that still has to run on older Pythons.
To get the most out of this tutorial, you should be comfortable running Python scripts from a terminal. Some familiarity with type hints will help in one section, though you’ll get the background you need as you go.
Note: The examples in this tutorial use Python 3.15.0rc1, so some details may shift slightly before the final release on October 1.
You’ll work through this tutorial with a small command-line tool and a few demo modules. You can download all of them here:
Get Your Code: Click here to download the free sample code you’ll use to defer heavy modules and speed up your CLI startup with Python 3.15.
Take the Quiz: Test your knowledge with our interactive “Python 3.15 Preview: Lazy Imports” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Python 3.15 Preview: Lazy ImportsTest your understanding of Python 3.15 lazy imports, from the lazy keyword and __lazy_modules__ to the imports that have to stay eager.
Try Lazy Imports on a Python 3.15 Pre-Release
Python 3.15 won’t reach its final release until October, so you’ll need a pre-release build. The quickest path is uv, which downloads a prebuilt interpreter for your platform. If you don’t have it yet, then Real Python’s guide covers installing uv on every platform. Once uv is in place, you can run the pre-release interpreter straight away:
$ uv run --python 3.15 python -VV
Python 3.15.0rc1 (main, Aug 25 2026, 13:50:37) [Clang 22.1.3 ]
A single -V would print just the version number. Doubling it to -VV adds the build date and the compiler, which is worth having while you’re juggling more than one interpreter and want to be certain which one you landed on.
Running pyenv install 3.15.0rc1 gets you to the same place by a different route. It compiles CPython from source, so you’ll need a build toolchain first: a C compiler, the Python headers, and a handful of system libraries. That takes longer, but it’s the option to reach for when you want to configure the build yourself.
You can also run a pre-release version of Python in Docker and keep it off your machine entirely. The pre-release installation guide covers all three routes in more detail.
Next, unpack the sample code you downloaded and change into the folder it creates. That folder is home base for the rest of this tutorial, and every cd after this one is relative to wherever the last one left you:
$ cd materials-python315-lazy-imports/
Now create a virtual environment on the pre-release and activate it, so that a bare python means 3.15 in every folder you visit. Pinning with uv python pin doesn’t do that, because the .python-version file it writes only applies to uv run:
$ uv venv --python 3.15
Using CPython 3.15.0rc1
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
That creates a .venv/ folder inside the sample code folder. Activating it is the step that puts the pre-release on your path:
With the environment active, a bare python is the pre-release build:
$ python -VV
Python 3.15.0rc1 (main, Aug 25 2026, 13:50:37) [Clang 22.1.3 ]
That’s the interpreter that every bare python command from here on will use.