Skip to content

The publication for web craftspeople Tuesday, 8 September 2026

Back-end

Python 3.15 locks in: lazy imports, UTF-8 by default, and a sharper JIT

Python 3.15 shipped its final release candidate on 1 September 2026, ahead of a 1 October launch. Explicit lazy imports, UTF-8 as the default encoding and a reworked JIT headline an update tuned for startup time and speed.

On 1 September 2026, Python 3.15 cleared its last milestone before launch: the 3.15.0rc2 release candidate, now feature-frozen. The final version is due on 1 October. Three changes stand out for web back-ends: explicit lazy imports, UTF-8 as the default encoding, and a substantially reworked JIT compiler.

A release candidate that is already frozen

rc2 closes the development phase: no further features will be added, and the ABI stays stable through to the final release. It bundles roughly 144 fixes reported since rc1 — a cycle now focused on stabilisation.

MilestoneDateScope
3.15.0rc1August 2026Feature freeze
3.15.0rc21 September 2026Final RC, ABI frozen, ~144 fixes
3.15.0 final1 October 2026Production release

For teams running Python services in production, the testing window is closing: now is the time to validate dependencies against the RC, with the same production discipline — a systemd-managed service, a reverse proxy — as any other back-end.

PEP 810: lazy imports, but explicit

The most visible change is a new soft keyword, lazy. A module marked lazy is only loaded on first access to one of its attributes, cutting startup latency and the memory footprint of apps that import a lot without using everything.

lazy import json
lazy from pathlib import Path

print("...")                    # json et pathlib pas encore charges
data = json.loads('{"cle": "valeur"}')   # json est charge ici
racine = Path(".")              # pathlib est charge ici

A compatibility mode exists through the __lazy_modules__ variable, handy for making imports lazy without rewriting each line. The gain is clearest on command-line programs, where launch time is paid on every invocation — familiar ground for CLI tooling.

The catch is in the word “explicit”: unlike an automatic mechanism, PEP 810 leaves the choice to the developer, import by import. Side effects triggered at import time — plugin registration, opening connections — must never be made lazy without analysis.

UTF-8 by default: the end of a silent bug source

With PEP 686, Python now uses UTF-8 as the default encoding, independent of the system environment. A call like open('data.txt') reads as UTF-8 with no configuration, ending behaviour gaps between a developer’s machine and a server whose locale differs.

The historical behaviour remains available: PYTHONUTF8=0 or the -X utf8=0 option restore locale-dependent encoding while the rare scripts that relied on it are migrated.

A file opened without specifying an encoding now reads as UTF-8, whatever the server: the main cause of environment drift is gone.

A reworked JIT and two new built-in types

The JIT compiler, experimental in earlier versions, has been “significantly upgraded” according to the release notes, which report gains of roughly 8–13% depending on the platform. The 64-bit Windows binaries also adopt the tail-calling interpreter. Like other ecosystems betting on execution speed, Python is working to cut the cost of interpretation.

On the type front, two additions land in builtins: frozendict, an immutable and hashable dictionary (PEP 814), and sentinel, for creating unique sentinel values with a readable representation (PEP 661).

>>> config = frozendict(hote="db.interne", port=5432)
>>> config["port"]
5432
>>> config["port"] = 5433
TypeError: 'frozendict' object does not support item assignment

Watch out. Lazy imports shift the loading cost to first access: an import exception no longer surfaces at startup but mid-execution. On a web service, a configuration error once caught at boot can turn into a production incident. Reserve lazy imports for heavy modules with no side effects.

Key takeaways

  • Python 3.15 has been frozen since the 1 September rc2; the final version ships on 1 October 2026.
  • PEP 810 brings explicit lazy imports (lazy import), effective on startup of tools and apps.
  • PEP 686 makes UTF-8 the default, reversible via PYTHONUTF8=0.
  • The JIT improves, and frozendict/sentinel join the built-in types.

Lazy imports are the feature I was waiting for most, but also the one that demands the most discipline. On my own services I’ll only enable them on heavy modules verified to have no side effects: an import that fails mid-request rather than at startup is the kind of surprise you pay dearly for on a Friday night. — Simon Janvier

Primary source: “What’s New In Python 3.15”, the official documentation, and the 3.15.0rc2 release candidate notes.

Read next