Python 3.15 arrives with lazy imports and a built-in sampling profiler

Python 3.15 arrives with lazy imports and a built-in sampling profiler

Python 3.15 is out, and in a post dated 12 October 2026 a developer who maintains open source projects walks through what he finds most interesting. He points readers to the What's new in Python 3.15 guide, curated this year by Hugo van Kemenade, the 3.14 and 3.15 release manager. His own angle is practical: he keeps his main projects working on every supported Python version, so the release lets him say goodbye to 3.10 and start using features from 3.11.

The feature he is most excited about is explicit lazy imports from PEP 810. You write lazy import json or lazy from pathlib import Path, and the module is imported only the first time its symbols are used in the code that follows. The author's LLM CLI tool supports plugins, and he had to recommend manual lazy imports in the plugin documentation, because merely installing plugins with heavy dependencies such as sentence_transformers could add multiple seconds to every invocation of the llm command. In his words, lazy imports directly address this startup cost.

Second is unpacking in comprehensions, from PEP 798 by Adam Hartz and Erik Demaine. It extends the unpacking syntax of PEP 448, which landed in Python 3.5 in 2015. With lists = [[1, 2], [3, 4], [5]], [*L for L in lists] gives [1, 2, 3, 4, 5], equivalent to [x for L in lists for x in L]. The same works for sets, where {*s for s in sets} flattens a list of sets, and for dicts, where {**d for d in dicts} merges them, with later keys winning: [{'a': 1}, {'b': 2}, {'a': 3}] gives {'a': 3, 'b': 2}.

Third is a sampling profiler. The existing tracing profiler has been renamed from cProfile to profiling.tracing, and a new sampling profiler called Tachyon, also known as profiling.sampling, joins it in the standard library. Sampling profilers periodically capture stack traces from running processes and use them to work out which functions spend the most time. The author says they have very low overhead and give deep insight into running systems without instrumenting them first. He had used tools like py-spy for this before; now the capability is built in. To try it on a running Python 3.15 process you pass its PID: sudo uv run --python 3.15 python -m profiling.sampling attach 1234, then interact with the program and press Ctrl+C to stop and see a report. He needed sudo on macOS. The profiler also produces flame graphs and heat maps, and can output a format viewable in the Firefox profiler UI.

On speed, the news is modest. Miguel Grinberg investigated How fast is Python 3.15? against the 3.15.0rc3 release and found performance mostly the same as 3.14, apart from the experimental JIT. The JIT gave a 1.2x boost over the standard 3.15 interpreter on a Fibonacci test, the first time Grinberg had observed a meaningful JIT gain. His exploration of 3.14 last year found significant boosts over 3.13 across many more categories.

The author also shows how he upgraded with uv: uv self update so uv knows about the release, uv python install 3.15, uv python pin --global 3.15 to make it the default for every uv run unless a project pins another version, and uv run python --version to confirm. He reinstalled his uv-installed tools with commands like uv tool upgrade datasette --python 3.15.

Finally, the release means Python 3.10, released in 2021, is officially no longer supported. His policy is to keep main projects working on every supported version, so he can now rely on 3.11 features. He singles out tomllib; TaskGroup and timeout() for asyncio, which Datasette uses heavily; the datetime.UTC alias for datetime.timezone.utc; and SQLite upgrades: setlimit() and getlimit(), create_window_function() for custom window functions written in Python, blobopen() for partial reads and writes of large BLOB values, and set_authorizer(None) to remove an authorizer. Datasette had a workaround for that last one, and his first Datasette pull request removes it. There are also typing improvements. He plans to land 3.11 improvements across a number of projects over the next few weeks, and has updated his click-app, datasette-plugin, python-lib and llm-plugin cookiecutter templates to test against Python 3.11 through 3.15.

Key facts

  • Python 3.15 adds explicit lazy imports (PEP 810): lazy import json defers the import until the symbols are first used, which targets slow startup in plugin-heavy tools.
  • PEP 798 brings unpacking in comprehensions, so [*L for L in lists] flattens nested lists, and {**d for d in dicts} merges dicts.
  • A new sampling profiler, Tachyon (profiling.sampling), joins the standard library; the old tracing profiler is renamed from cProfile to profiling.tracing.
  • Per Miguel Grinberg's tests on 3.15.0rc3, performance is mostly the same as 3.14; the experimental JIT gave 1.2x on a Fibonacci test.
  • Python 3.10 is now officially unsupported, letting the author drop it and use 3.11 features such as tomllib, TaskGroup and timeout().

Why it matters

Python 3.15 is a feature release rather than a speed release. Explicit lazy imports give developers a language-level way to avoid paying for heavy modules at startup, a problem the author had been patching with manual workarounds in documentation. A profiler that ships in the standard library means a sampling tool is available without installing anything extra. The release also retires Python 3.10, which lets maintainers who track supported versions raise their minimum to 3.11 and use its features.

Who it affects

Maintainers of libraries and tools that follow the supported-version window are affected most, since 3.10 is now out of support. Authors of plugin-based command line tools gain the most from lazy imports, because installed plugins with heavy dependencies no longer need to slow every run. Developers who diagnose slow production processes get a built-in sampling profiler. Anyone hoping for a free speed-up will find little: performance is mostly the same as 3.14.

How to use it

To get the new interpreter with uv, run uv self update, then uv python install 3.15. Use uv python pin --global 3.15 to make it the default for uv run, unless a project pins another version, and check with uv run python --version. Tools installed with uv tool install need reinstalling against 3.15, for example uv tool upgrade datasette --python 3.15. For lazy imports, prefix an import with the lazy keyword. To profile a running process, attach with python -m profiling.sampling attach <PID>, interact with the program, then press Ctrl+C for the report. The author needed sudo on macOS.

How solid is it

This is a first-hand blog post by a developer who ran the uv upgrade steps and the profiler himself and links the official What's new in Python 3.15 guide. The language features come from named PEPs: PEP 810 for lazy imports and PEP 798 for unpacking in comprehensions. The performance claims are not his own measurements; they come from Miguel Grinberg's investigation against the 3.15.0rc3 release candidate, and the JIT figure rests on a single Fibonacci test.

Risks and caveats

Do not expect a faster interpreter: apart from the experimental JIT, performance is mostly the same as 3.14, and the 1.2x JIT gain was measured on one Fibonacci test against a release candidate. The JIT is described as experimental. Attaching the sampling profiler to a process required sudo on macOS. Moving to 3.11 is the author's own support policy for his projects, which he says he will roll out over the next few weeks; other projects will set their own minimum versions.

“Now this capability is baked into the standard library.”

— The author, on the new Tachyon sampling profiler