Python 3.15.0's first release candidate (RC1) shipped on August 4, 2026, locking the feature set—only clear bug fixes from here. RC2 is set for September 1, and the final 3.15.0 is planned for October 1. For teams that skipped the beta series, RC1 is the last window to run test suites and find breakage before someone else's production incident finds it for them.
3.15 is not just another syntax-sugar release. It moves startup speed, built-in immutable types, the standard library profiler, and the JIT roadmap all at once.
Key Numbers in 3.15
- Faster startup: PEP 810 introduces the
lazysoft keyword, deferring module loading until a used name is actually touched. Withlazy import pandas as pd, the module isn't loaded or added tosys.modulesuntilpd.DataFrame()is called. CLI tools and scripts that import a lot but use a little see significantly reduced startup time. It's explicitly opt-in, not a silent change to existing imports. - New built-in types:
frozendict(PEP 814) andsentinel(PEP 661).frozendictis an immutable built-in likefrozenset—a hashable, read-only dict that replaces the defensive copy pattern.sentinelmakes the "unique marker object" pattern (the hand-written_MISSING = object()) something the standard library and type checkers natively understand. One gotcha: frozendict inherits directly from object, not dict, soisinstance(x, dict)checks will silently reject it—library authors should useisinstance(x, (dict, frozendict))or checkcollections.abc.Mappinginstead. - Production-grade profiler: PEP 799 consolidates Python's profiling tools into a unified
profilingnamespace—profiling.tracing(deterministic call tracing, successor to cProfile) andprofiling.sampling(a high-frequency statistical sampler called Tachyon). Tachyon is the first zero-overhead statistical profiler in the standard library: it reads process call stacks externally without instrumenting function calls, samples at up to 1,000,000 Hz, attaches to running processes without restarts or code changes, and supports async functions, free-threaded builds, and multi-threaded programs. cProfile remains as a backward-compatibility alias. - Real JIT progress: The 3.15 JIT is 8–9% faster than the standard interpreter on x86-64 Linux (geometric mean) and 12–13% faster on AArch64 macOS. The team rewrote the tracing frontend, added basic register allocation, and increased JIT code coverage by 50%. But it remains experimental, requiring the
--enable-experimental-jitbuild flag—don't use it in production. Stabilizing the JIT targets 3.16. - Other changes: UTF-8 as the default encoding (PEP 686 rollout continues), unpacking in comprehensions (PEP 798), TypedDict support for typed extra keys (PEP 728), TypeForm (PEP 747), and disjoint bases in the type system (PEP 800). Official Windows 64-bit binaries use the tail-calling interpreter, and official macOS binaries install free-threading support by default.
A Governance Turning Point for the JIT Roadmap
Last month's core dynamic was the Steering Council giving CPython's JIT a six-month ultimatum: write a standard-track PEP or remove the JIT from main. The response was PEP 836, "JIT Go Brrr: The Path to a Supported JIT Compiler for CPython," published July 2 by Savannah Ostrowski, Ken Jin, and Brandt Bucher. It lays out a roughly two-and-a-half-year roadmap from 3.16 to 3.17: the JIT moves from today's trace-based recording toward method-based compilation, and by 3.17 it should deliver at least a 20% improvement over the free-threaded interpreter without regressing debugger and profiler support, while clarifying how packagers distribute the JIT. The PEP is still a draft and the council hasn't ruled, but turning a governance ultimatum into a public roadmap within a month is worth watching in itself.
Synchronized Shocks in the Packaging Ecosystem
In the same window, Astral shipped two breaking minor releases. uv 0.12.0 (July 28) is the first minor bump since March; Ruff 0.16.0 came five days earlier. uv's visible change is that uv init now generates packagable projects with a src/ layout; the subtler but important half is fixing --require-hashes, which previously only warned instead of verifying hashes in requirements.txt, plus rejecting MD5-only digests and wheels that would overwrite the interpreter (including Python.exe—the old check missed this on case-insensitive filesystems). Ruff 0.16.0's default rules jumped from 59 to 413, which will flag far more issues across existing projects. Separately, PyPI announced it will stop accepting files added more than 14 days after release, nominations for the first Python Packaging Council are opening, and core developer Petr Viktorin was named a PSF Fellow.
A Reminder for Library Maintainers
RC1 locks features; RC2 locks code. If you maintain a third-party library, test against RC1 now and publish 3.15 wheels to PyPI—binary wheels built against RCs remain valid for future 3.15 releases. Most application projects don't need to upgrade on day one; treat 3.15.0 like any .0 release and wait for 3.15.1 or .2, unless lazy imports or the JIT happen to solve a specific problem you already have. Third-party support typically lags the language release by weeks to months—library authors testing early is what lets downstream keep up.