
Python 3.15.0rc2 dropped September 1 as the final preview before the October 1 general release. The feature set is locked — only bug fixes land from here. That gives you 26 days to test your code against a release that changes startup behavior, adds a JIT speed bump you can actually measure, and finally puts an immutable dict in the standard library. If something breaks in your codebase, now is when you find out. Not on October 2.
Lazy Imports: The 70% Startup Win
PEP 810 introduces the lazy soft keyword, and it is the most consequential developer experience improvement Python has shipped in years. A lazy import defers module loading until the imported name is actually used. Until then, Python binds a lightweight proxy. Your startup code stays clean and organized at the top of the file; the interpreter only pays the import cost when your code actually needs it.
The practical impact is significant. CLI tools and web applications that import dozens of libraries but only use a fraction on any given invocation can cut startup times by 50 to 70 percent. Those are Meta’s numbers from production deployments. The migration cost is one keyword per line:
# Before
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# After — loads only when referenced
lazy import numpy as np
lazy import pandas as pd
lazy import matplotlib.pyplot as plt
This is entirely opt-in. Regular import behaves exactly as before. If you need backward compatibility with older Python versions, a lazy_modules config key in your package startup file handles the fallback gracefully.
JIT Compiler: Real Numbers, Honest Framing
The JIT gets a meaningful upgrade in 3.15. A new tracing frontend records the execution paths your code actually takes, giving the compiler better information about what to optimize. Improved register allocation keeps values in CPU registers across consecutive operations rather than bouncing through the stack. The result: 8 to 9 percent geometric mean speedup on x86-64 Linux, and 12 to 13 percent on AArch64 (Apple Silicon).
To be direct about what that means: Python is not PyPy. Float-heavy and loop-heavy workloads benefit far more than recursive code. Real-world ETL benchmarks show around 7 percent throughput improvement with zero code changes. These numbers compound with what shipped in 3.11, 3.12, 3.13, and 3.14. The trajectory is real, even if a single release does not transform Python into a systems language.
frozendict: Finally Built In
PEP 814 adds frozendict as a true built-in type. It is immutable, ordered, and hashable — provided all its values are hashable. That last part matters: it means you can use a frozendict as a dictionary key or set member, which types.MappingProxyType cannot do.
The use cases that required workarounds for years are now straightforward:
# Old workarounds
key = tuple(sorted(params.items())) # verbose
config = types.MappingProxyType(settings) # not hashable
# Python 3.15
config = frozendict({"debug": False, "workers": 4})
cache[config] = result # valid — frozendict is hashable
It integrates with json, pickle, copy, pprint, marshal, and decimal out of the box. No special handling. Thread-safe by default since mutation is impossible. This has been a long time coming, and it is implemented correctly.
Tachyon: Production Profiling Without the Pain
The new profiling.sampling module (PEP 799) brings Tachyon — a statistical sampling profiler — into the standard library. It samples at up to one million hertz with near-zero overhead, which makes it appropriate for production use. You can attach to a running process by PID without restarts or code changes:
python -m profiling.sampling run --format flamegraph -o report.html app.py
Output options include interactive HTML flamegraphs (D3.js), collapsed stacks for external tools, and pstats-compatible output. It understands threads and async code. The old profile module is now deprecated and will be removed in Python 3.17. If you are still using it, now is a reasonable time to migrate.
Breaking Changes to Check
A short list of removals that may affect existing code:
datetime.utcnow()removed — usedatetime.now(timezone.utc)- AST node constructors now raise
TypeErroron invalid arguments (wasDeprecationWarningsince 3.13) strptime()with%dand no year directive raisesValueError__cached__is no longer set on modules — use__spec__.cachedctypes.SetPointerType()removed (deprecated since 3.13)
If your codebase has not addressed deprecation warnings from the 3.13 cycle, RC2 is the moment of reckoning.
Test It Now
Installing RC2 takes one command with pyenv:
pyenv install 3.15.0rc2
python3.15 -m venv .venv315 && source .venv315/bin/activate
pip install -r requirements.txt
pytest
Run your test suite. Report regressions at bugs.python.org. The window for fixes is closing. The full release notes and RC2 downloads are on python.org, and the official What’s New document covers every change in detail. October 1 ships whether or not your library is ready — but you still have time to make sure it is.













