
Python 3.15 beta 3 dropped on June 23, 2026. Feature freeze is in — the list is final. The headline features are practical, immediately testable, and fix problems Python developers have been patching with third-party tools for years: startup latency, immutable configs, and production profiling. Here’s what you’re getting in October, and how to try it today.
Lazy Imports: The Startup Fix Python CLI Developers Have Waited For
Python’s startup latency has been a genuine complaint, especially for CLI tools that import heavyweight libraries like pandas or NumPy regardless of which subcommand runs. PEP 810 addresses this directly with a lazy soft keyword that defers module loading until first use.
The syntax is clean:
lazy import pandas as pd
lazy import matplotlib.pyplot as plt
lazy from pathlib import Path
# pandas and matplotlib are not loaded yet
# loading happens on first attribute access:
df = pd.read_csv("data.csv")
Under the hood, Python creates a types.LazyImportType proxy stored in sys.lazy_modules instead of sys.modules. On first attribute access, the actual import fires — this is called “reification” — and the proxy is replaced with the real module. Existing code that interacts with the module object works identically.
The performance numbers are meaningful. The pypistats CLI went from 104ms cold start to 36ms when all imports were made lazy — a 3x improvement. Meta, at enterprise scale, reported 70% reduction in initialization time after converting libraries to lazy imports. Hugo van Kemenade documented similar 3x gains on his own tooling.
One restriction: lazy works at module level only. You cannot use it inside functions, class bodies, or try/except blocks. Enable it globally with the -X lazy_imports flag or PYTHON_LAZY_IMPORTS=1 environment variable without changing any source code. JetBrains has already covered the migration path for PyCharm users, though IDE support is still catching up.
This matters most for CLI tools and applications with large, partially-used import trees. If your code imports 20 libraries and a given invocation uses 5 of them, lazy imports eliminate the overhead of loading the other 15 on every run.
frozendict: Immutable Dicts Are Now a Built-in
The frozendict PyPI package had 36,000 weekly downloads before this PEP was accepted. That number tells you everything about the gap this fills. PEP 814, accepted by the Python Steering Council in February 2026, makes frozendict a built-in type — no import required in Python 3.15.
frozendict is an immutable mapping that is hashable when all its keys and values are hashable. That hashability is what makes it genuinely useful where a regular dict falls short:
# Use as a dict key (impossible with regular dict)
cache: dict[frozendict, Result] = {}
cache[frozendict(model="gpt4", temperature=0.7)] = result
# Works with lru_cache (regular dict arguments raise TypeError)
@functools.lru_cache()
def process(params: frozendict) -> Result:
...
# Safe default arguments — no mutable default trap
DEFAULT_CONFIG = frozendict(timeout=30, retries=3, debug=False)
# Order-independent equality
frozendict(x=1, y=2) == frozendict(y=2, x=1) # True
The thread-safety angle is worth noting as free-threading builds (no GIL) become more practical in Python 3.14 and 3.15: sharing immutable config across workers is inherently safe without locks. frozendict fits naturally there.
The Steering Council accepted an O(n) shallow copy implementation from a regular dict. There was community debate about an O(1) .freeze() method — that optimization was deferred but not ruled out for a future release.
Tachyon: A Sampling Profiler in the Standard Library
Python’s profiling story has always had a gap: cProfile is a deterministic tracer that adds overhead to every function call, making it unsuitable for production use. The community filled this gap with py-spy, a third-party sampling profiler. Python 3.15 ships a built-in answer.
PEP 799 reorganizes profiling into a new profiling package with two modules: profiling.tracing for deterministic tracing (the relocated cProfile) and profiling.sampling for the new Tachyon statistical sampler.
Tachyon works by periodically capturing stack snapshots rather than instrumenting every call. Overhead is near zero, sampling rates go up to 1,000,000 Hz, and it can attach to a running process by PID without requiring a restart:
# Attach to a running process by PID
python -m profiling.sampling attach 1234
# Profile a script with an interactive flamegraph
python -m profiling.sampling run my_app.py --flamegraph
# Analyze GIL contention directly
python -m profiling.sampling run --mode gil my_server.py
# Real-time terminal interface
python -m profiling.sampling run my_app.py --live
Output formats cover the standard toolkit: pstats-compatible stats, collapsed stacks for flame graphs, interactive HTML flame graphs, Firefox Profiler format, line-level heatmaps, and a live TUI. The async-aware mode (--async-aware) handles coroutine stacks correctly, which has been a consistent pain point with existing tools.
This is not a dramatic technical breakthrough — py-spy has offered most of this for years. What changes is that you no longer need to convince your ops team to allow a third-party tool in production. It’s stdlib. That matters in practice.
Everything Else Worth Knowing
- Free-threading ABI stability (PEP 803): Python 3.15 introduces
abi3tcompatibility for free-threaded CPython builds. C extension authors can now compile a single wheel covering multiple Python minor versions without the GIL. The no-GIL path is getting serious infrastructure. - JIT improvements: 8–9% geometric mean improvement on x86-64 Linux, 12–13% on AArch64 macOS over the standard interpreter.
- Frame pointers by default (PEP 831): CPython now builds with
-fno-omit-frame-pointer. System-level profilers like perf and eBPF tools now get accurate Python stack traces without extra configuration. - UTF-8 as default encoding (PEP 686): File I/O without an explicit
encodingargument now defaults to UTF-8. Long overdue.
How to Try Beta 3 Now
Python 3.15.0b3 is available on python.org and via pyenv:
pyenv install 3.15-dev
pyenv local 3.15-dev
python --version # Python 3.15.0b3
Do not use this in production — the ABI can still change before rc1 on August 4. But for testing lazy imports on your CLI tool, experimenting with frozendict, or kicking Tachyon’s tires, beta 3 is stable enough. Beta 4 ships July 18. Final release: October 1, 2026.
Python 3.15 is among the most practical performance-and-ergonomics releases in recent cycles. The lazy import benchmarks alone are worth paying attention to if you maintain anything with a startup latency problem.













