Python's 2026 Roadmap: Lazy Imports, Rust in CPython, D-Strings, and the End of the GIL
Python 3.15 brings lazy imports and free-threading goes official. Rust lands in CPython 3.16. D-strings kill textwrap.dedent(). Calendar versioning gets rejected. Here's everything coming to Python in 2026.
On this page
If you thought Python 3.14 was a big deal, 2026 is shaping up to be even more transformative. We’re looking at lazy imports landing for real, Rust code entering CPython, the GIL becoming officially optional, and a string prefix that makes textwrap.dedent() obsolete.
This isn’t a wishlist. These are accepted PEPs, active implementations, and official roadmap items. Let’s break down what’s actually happening.
Lazy imports: the performance feature Python always needed (PEP 810)
Status: Accepted, available in Python 3.15.0a7
This is the headline feature of Python 3.15. After years of debate (and the rejected PEP 690), the Steering Council accepted PEP 810 — explicit lazy imports.
The problem is well-known: Python eagerly loads every module at import time. For a Django management command that imports half the framework just to print a help message, that means hundreds of milliseconds wasted before a single line of your code runs.
The fix is elegant:
lazy import numpy as np
lazy from pandas import DataFrame
# numpy and pandas don't load until you actually use them
df = DataFrame({"a": [1, 2, 3]}) # pandas loads HERE
Why this matters for production
The CPython team found that 17% of standard library imports are already placed inside functions to defer loading. That’s developers manually working around a language limitation. lazy import makes this optimization explicit, clean, and maintainable.
Real-world impact:
- CLI tools — Click-based CLIs and Django management commands see dramatically faster startup
- Microservices — Cold start times drop when unused imports don’t load
- Type checking — No more
if TYPE_CHECKING:dance for import-heavy type annotations - Large codebases — Enterprise apps with deep dependency trees benefit most
What about side effects?
The key design decision: lazy only applies to modules that are safe to defer. If a module has side effects on import (like registering signal handlers), you import it normally. The keyword is opt-in per import statement — no global switches, no surprises.
import logging # Normal — has side effects (configures root logger)
lazy import numpy as np # Lazy — pure library, safe to defer
Free-threading goes official: the GIL is now optional
Status: Official in Python 3.14+, maturing in 3.15
Python 3.13 introduced free-threading as experimental. Python 3.14 promoted it. Now in 3.15, the --disable-gil builds are stable enough for production workloads, and the ecosystem is catching up.
What’s new in 2026:
- PEP 803 proposes
abi3t, a stable ABI variant for free-threaded builds. This means extension authors can ship a single wheel that works for both GIL-enabled and GIL-disabled Python — no more doubling your build matrix. - Major libraries (NumPy, pandas, scikit-learn) now ship free-threaded wheels
- The performance gap between GIL and no-GIL builds has narrowed to single-digit percentages for single-threaded code
# Python 3.15 with free-threading
import concurrent.futures
import hashlib
def compute_hash(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
# Actually runs in parallel now — no GIL blocking
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
results = list(executor.map(compute_hash, large_dataset))
For CPU-bound work that previously required multiprocessing (with all its serialization overhead), threads now just work.
D-strings: textwrap.dedent() is dead (PEP 822)
Status: Draft, targeting Python 3.15
Every Python developer has written this:
import textwrap
def get_query():
return textwrap.dedent("""\
SELECT *
FROM users
WHERE active = true
ORDER BY created_at DESC
""")
PEP 822 introduces the d prefix that handles indentation automatically:
def get_query():
return d"""
SELECT *
FROM users
WHERE active = true
ORDER BY created_at DESC
"""
The d prefix uses the same algorithm as textwrap.dedent() but at compile time. It combines with other prefixes too: df"..." for dedented f-strings, dr"..." for dedented raw strings, even dt"..." for the new template strings from Python 3.14.
This is a small quality-of-life improvement, but it removes one of those constant paper cuts that make Python code slightly uglier than it needs to be.
Rust is coming to CPython — targeting 3.16
Status: Active development, PEP expected July 2026
This is the big architectural shift. The “Rust for CPython” working group announced in April 2026 that Rust code will be included in CPython 3.16 (October 2027).
The roadmap
| Timeline | Milestone |
|---|---|
| March 2026 | Build system work complete — CI green on all platforms |
| April 2026 | Internal Rust API design begins, select first extension module |
| May 2026 | Finalize API design, sprint at PyCon US |
| June 2026 | Start writing the PEP |
| July 2026 | Submit PEP for discussion |
| May 2027 | Python 3.16 beta 1 |
The approach is conservative and deliberate:
- Start with a single extension module reimplemented in Rust
- The Rust API remains internal until a later PEP stabilizes it
- The Rust team has been actively collaborating with CPython maintainers
What this means
Rust in CPython isn’t about rewriting Python in Rust. It’s about replacing performance-critical C code with memory-safe Rust while maintaining the same Python API. Think: parsing, hashing, serialization — the parts where C bugs become CVEs.
For Python users, nothing changes. Your code is still Python. But the interpreter underneath gets safer and potentially faster.
Security patches: update your older Pythons
Three security releases dropped in March 2026:
- Python 3.12.13 — Security-only (build from source)
- Python 3.11.15 — Security-only
- Python 3.10.20 — Security-only
Key CVEs patched:
- CVE-2026-24515 and CVE-2026-25210 — XML parsing vulnerabilities via bundled libexpat (upgraded to 2.7.4)
- XML memory amplification bug
- Control character rejection in HTTP headers and URL parsing
If you’re running 3.12 or older in production, patch now.
Other PEPs worth watching
PEP 806: mixed sync/async context managers
Currently, mixing with and async with requires nesting:
# The staircase of doom
async with resource_a() as a:
with resource_b() as b:
async with resource_c() as c:
# finally, your actual code
PEP 806 would allow:
async with resource_a() as a, resource_b() as b, resource_c() as c:
# clean and flat
PEP 820: C API slot redesign
A PySlot tagged union that modernizes the C extension API. The C API Working Group voted 4-0 to recommend acceptance. This matters for extension authors and embedding scenarios.
Calendar versioning (PEP 2026) — rejected
The proposal to rename Python 3.15 to “Python 3.26” (using the release year) was rejected by the Steering Council. Python sticks with sequential version numbers. So it’s 3.15, not 3.26.
The big picture: Python in 2026
Here’s what stands out when you look at all these changes together:
Python is solving its historical weaknesses. The GIL was the #1 complaint from systems programmers — it’s becoming optional. Import performance was a known bottleneck — lazy imports fix it. C memory safety issues generated CVEs — Rust addresses the root cause.
The pace is accelerating. The annual release cadence (PEP 602) means features land faster. Python 3.14 gave us t-strings and free-threading. Python 3.15 gives us lazy imports and d-strings. Python 3.16 will bring Rust.
The language is maturing, not stagnating. These aren’t flashy syntax additions for the sake of novelty. They’re pragmatic solutions to real problems that production Python developers face daily.
If you’re still on Python 3.11 or 3.12, the gap is growing. The upgrade path from 3.11 to 3.15 isn’t painful (I wrote a detailed guide covering 3.11 through 3.14), and the benefits — performance, safety, developer experience — compound with each version.
2026 is the year Python stops apologizing for its limitations and starts fixing them.