Python 3.15.0 Ships October 9 After Lazy-Import Bugs Forced an Unplanned Third Candidate
Software / news
Python 3.15.0 Ships October 9 After Lazy-Import Bugs Forced an Unplanned Third Candidate
The release team had called rc2 final on September 1. Late blockers in PEP 810 added an rc3 on October 2 and pushed the stable build to October 9.
Python 3.15.0 went out on October 9, 2026, eight days after the October 1 date the release team set in September, because late bugs in the new lazy import statement earned the release a third candidate that nobody had planned.
The 3.15.0 release page lists the stable release with an Oct. 9 date. The September 1 announcement of release candidate 2 had called rc2 "the final planned release candidate" and set the final for October 1.
Why a third candidate appeared on October 2
The rc3 release notes, dated Oct. 2, open by calling it "a surprise third release candidate." They say the team "got some last-minute lazy-import release blockers" and wanted time to test the fixes. The final moved back a week from the original date.
The rc3 build carries around 156 fixes from 82 contributors since rc2. The rc2 build had around 144 fixes from 76 contributors since rc1. The notes do not list which lazy-import bugs were the blockers, so the exact failures are not public in the pages the release team signed.
| Build | Date | Fixes since previous |
|---|---|---|
| 3.15.0 rc1 | Aug. 4 | not stated |
| 3.15.0 rc2 | Sept. 1 | around 144, 76 contributors |
| 3.15.0 rc3 | Oct. 2 | around 156, 82 contributors |
| 3.15.0 final | Oct. 9 | not stated |
PEP 790 now lists the rc3 and final dates as actual, with no explanation attached.
What lazy import does, and where it refuses to work
PEP 810 adds lazy as a soft keyword. Under What's New in Python 3.15, lazy import json creates a lightweight proxy, and the module loads on first use. A missing module therefore fails at first use instead of at startup, and the traceback shows both the access site and the original import line.
The statement is module-scope only. Inside a function, a class body or a try block it raises SyntaxError, and so do lazy from module import * and lazy from __future__ import .... Code that must also run on older interpreters can list names in __lazy_modules__. The feature was contributed by Pablo Galindo Salgado and Dino Viehland.
Global control comes through -X lazy_imports=all|normal, the PYTHON_LAZY_IMPORTS variable and sys.set_lazy_imports_filter(), which takes a callable that returns True to allow laziness.
The sys.lazy_modules argument, left open
On August 12 Viehland proposed removing sys.lazy_modules as misleading. Marc-André Lemburg voted against, and Damian Shaw said pip must resolve every lazy import before installing wheels and measured the list as far faster than walking sys.modules. Hugo van Kemenade floated renaming it to sys._lazy_modules for 3.15. The thread text read for this story shows no final decision.
Tooling that has to catch up
Libraries that register handlers or change global state at import time break under laziness. Lifeguard, published under the facebook GitHub organisation, is a Rust static analyzer that flags those modules. Its README says to pass --python-version 3.15 to analyze the new syntax. It installs with pip install lifeguard-lazy-imports, uses the MIT licence, had 103 stars when read, and is labelled beta, aimed at general use by the 3.15 final.
Lifeguard says it was tested on Python 3.12 and 3.14 and treats any module it cannot confirm as unsafe.
The rest of the release, and one install snag
The release page reports a 7-8% geometric-mean speedup from the upgraded JIT on x86-64 Linux over the standard interpreter, and 11-12% on AArch64 macOS over the tail-calling interpreter. Both are the release team's own figures. A separate benchmark on this site measured 20% on recursion. The macOS installers now include free-threading, UTF-8 is the default encoding, and sentinel and frozendict are built in. The deprecation of re.match is covered in our earlier report.
macOS 27.0 users get a warning: IDLE and other tkinter apps may hang when opening dialogs, tracked in issue 158053, and the page suggests holding off on that OS upgrade.
Packaging is the other snag. The PyPI metadata for litellm 1.104.2 declares requires_python as <3.15,>=3.10, which excludes 3.15 outright. The next date to watch is the first 3.15.1 maintenance build, which the release page does not schedule.
Sources
More in Software
- 01LiteLLM's Rust Gateway Claims 15x Throughput, but Its Docs List Four Routes and No BenchmarksA June 22 blog post promised OCR, chat and a router by mid-September. The beta docs page read on October 10 shows a narrower path and a Docker image that is not published.
- 02Diagram Design Passes 47,900 Stars, and Its README Tells Git Users to Pick MermaidThe agent skill draws 44 diagram types as a single HTML file. Its own README admits layouts vary between runs, and five export bugs were filed on October 6.
- 03Anthropic's Knowledge-Work Plugins Have 28,300 Stars, a Datadog URL Due to Break and a Contribution Guide the CI OverridesThe 11-plugin repo is Apache-2.0 and trending. Its README asks for pull requests, a workflow closes them, and 76 issues sit open.
- 04Unison Cloud Goes MIT, but Its Local-Run Guide Still Pulls Nimbus From a Private RepoPaul Chiusano's Oct. 8 post open-sources the worker node, API server and web UI, while the repo's own instructions show a credentials step the post never mentions.