Originally published at https://tekmag.thsite.top/whats-new-in-python-3-15/
Python 3.15.0 lands on October 1, 2026, headlined by lazy imports, a hashable frozendict built-in, and a JIT compiler that now runs about 8 percent faster on x86-64 Linux. The Release cycle ships alongside security patches for the 3.10, 3.11, and 3.12 branches that most production systems still run, and the feature branch for Python 3.16 has already accepted PEP 828, which closes a nine-year language gap by letting async generators use yield from.
Python's release train runs on a fixed clock. PEP 790, the 3.15 release schedule, pins the final 3.15.0 release to October 1, 2026, after RC2 went out on September 1. The ABI has been frozen since RC1 on August 4, so the feature set is locked and the remaining work is polish. A few weeks after 3.15 ships, development on 3.16 continues in parallel, and its most anticipated PEP was accepted on August 3, 2026. In other words, there is a lot to check before the October deadline, and a clear look at what the next version brings.
Our angle in this piece: the 3.15 release itself, the security releases that already shipped, and the 3.16 work in flight. All claims below trace to the official PEPs, the release-manager announcements on blog.python.org, and security advisories from the upstream project and SUSE. Sources disagree on one performance number, and we flag where they do.
Key Takeaways
- Python 3.15.0 final releases October 1, 2026; RC2 is the last candidate, out September 1.
- PEP 828, accepted August 3, 2026, brings
yield fromto async generators in Python 3.16, the version that ships in October 2027. - The experimental JIT now delivers an 8 to 9 percent geometric-mean speedup on x86-64 Linux, up from 5 to 6 percent in March. It stays off by default.
- The August security release (3.12.14, 3.11.16, 3.10.21) fixes two notable CVEs, including a CVSS 8.6 stack overflow in XML parsing.
- PEP 686 makes UTF-8 the default encoding for
open(), a breaking change that mainly affects Windows. - Only about 9.4 percent of the top 360 PyPI packages declared 3.15 support as of RC1; pandas, boto3, pydantic, and scipy were not ready.
What's new in Python 3.15
Python 3.15 is the first release of the PEP 602 annual cycle, and it lands several PEPs that have been in development for years. The ones with visible user impact:
| Feature | PEP | What it does |
|---|---|---|
| Lazy imports | PEP 810 |
lazy import stdlib defers loading standard-library modules until they are actually used. Startup-time tests report up to 70 percent faster startup for CLI tools. |
| frozendict | PEP 814 | A hashable, immutable dict built-in. After roughly a decade of debate, a stdlib type finally exists for set-of-keys and immutable-mapping use cases. |
| UTF-8 by default | PEP 686 |
open() without an encoding argument defaults to UTF-8 on every platform, instead of the locale encoding. |
| Unpacking in comprehensions | PEP 798 | Nested unpacking inside comprehension for-clauses, e.g. [x for i, *rest in items], which previously raised SyntaxError. |
| Sentinel type | PEP 661 | A sentinel() factory for unique singleton marker values, replacing the object() idiom. |
| Profiling package | PEP 799 | A dedicated profiler package plus the Tachyon high-frequency sampler. |
| Frame pointers | PEP 831 | Enabled by default, improving system-level observability of CPython processes. |
Real-world ETL benchmarks published alongside the RC2 report show about 7 percent throughput improvement with zero code changes, which compounds with the JIT work below. The RC2 coverage at byteiota collected much of the feature list we use here, but for release-critical claims we check against the PEPs and the official blog.
PEP 828: yield from in async generators
Python 3.16's headline feature, PEP 828 by Peter Bierma, accepted August 3, 2026, lets async generator functions delegate to subgenerators with the plain yield from syntax. This closes a gap that has been in the language since async generators arrived in PEP 525 in 2017. At the time, CPython maintainers deferred yield from support, citing a serious redesign of the generator implementation. Bierma's reference implementation, included with the PEP, argues that complexity is no longer a concern given nine years of generator-implementation work.
The PEP also adds a .value attribute to StopAsyncIteration so delegated async generators can return a value, mirroring how StopIteration.value works with sync generators. The syntax decision matters: the PEP rejected async yield from and settled on plain yield from for symmetry with synchronous code, so the same delegation pattern reads identically in both worlds.
async def agenerator():
yield 1
yield 2
return 3
async def main():
result = yield from agenerator()
assert result == 3
Until 3.16 ships, the workaround is a for/async for loop that manually yields each item from the subgenerator, which works but hides intent and makes asend(), athrow(), and aclose() delegation awkward. Web frameworks that build on async generators have shipped hand-rolled delegation workarounds that PEP 828 will eventually make redundant.
JIT improvements and performance
CPython's JIT compiler is still experimental and off by default, and that does not change in 3.15. What did change: a tracing-frontend rewrite pushed the speedup from 5 to 6 percent in March to 8 to 9 percent on x86-64 Linux as measured in the latest release cycle. On macOS AArch64 the JIT is faster than the tail-call interpreter by 12 to 13 percent. We attribute the 8 to 9 percent figure to the Real Python September roundup; the March JIT status post on blog.python.org reports 5 to 6 percent on x86-64 Linux. Both are correct for their respective measurement dates, and the direction is the same: the JIT is closing the gap to a practical win. You will need the right build flags to see the improvement, and the numbers are geometric means on benchmark suites, not wall-clock times for your workloads.
If runtime compilation is the area you are tracking, Craton Bolt's SQL-to-PTX compiler applies the same idea in a database context, which is useful context for why compiler work is spreading across the language and system stack.
Security patches for the older branches
The security team shipped Python 3.12.14, 3.11.16, and 3.10.21 on August 12, 2026. The two CVEs to know about first:
-
CVE-2026-4224 (CVSS 8.6) — a C stack overflow when
xml/Expat parses deeply nested DTD content models. It is a denial-of-service vector for anything that ingests untrusted XML, and the SUSE advisory for the Python update rates it 8.6. -
CVE-2026-3644 (CVSS 6.5) — incomplete control-character validation in
http.cookies, enabling HTTP header injection through crafted cookies.
The release also fixes a SourcelessFileLoader bypass for .pyc files (CVE-2026-2297), a tarfile header parsing issue (CVE-2025-13462, CVSS 2.0), and a path-traversal flaw in resource-argument validation (CVE-2026-3479). On top of the CVE fixes, tarfile's extraction filter now applies to symlink targets, webbrowser.open() rejects URLs that start with a dash, and quadratic-backtracking issues were fixed in csv.Sniffer, html.parser, and configparser.
The full changelog is in the Python Insider security release announcement. For teams already on those branches, this is a patch-now release: the XML DoS is the highest-severity item, and it applies to any service that parses XML from a network source. It's the same shape of problem we saw in Microsoft's August Patch Tuesday, where the zero-day on the active exploitation list was the item that mattered most.
Breaking changes and deprecations
Python does not remove working code casually, but every feature release carries removals. The ones that will surface in code review:
-
UTF-8 default encoding (PEP 686).
open()withoutencoding=now defaults to UTF-8 on Windows, instead of the system locale. Windows code that relies on locale-specific encoding for file I/O should break. This is the single most likely source of post-upgrade failures. -
datetime.utcnow()removed. Usedatetime.now(timezone.utc)instead. The deprecation started in 3.12; it is gone now. -
__cached__no longer set on modules. Use__spec__.cached. -
AST node constructors raise
TypeErroron invalid arguments, where 3.13 only emitted aDeprecationWarning. -
strptime()with%dand no year now raisesValueError. -
ctypes.SetPointerType()removed, deprecated since 3.13.
None of these affect code that pinned its target version and ran a modern test suite. They do affect code that leaned on locale-specific behavior or legacy APIs. Running your suite against 3.15 now will surface the failures ahead of the October 1 deadline, and the byteiota RC2 post lists the same set.
Migration guide for Python 3.15
If you are on 3.12 or 3.13 today, the path to 3.15 is short but check these in order:
1. Patch your current branch first. The August security release is independent of the 3.15 upgrade. CVE-2026-4224 affects the XML parsing code in all the supported 3.10/3.11/3.12 point releases, so that is a patch-now item regardless of your upgrade plans. If you are on 3.10, plan a skip to 3.11, 3.12, or 3.13 instead of holding on; 3.10 is close to end of life.
2. Run the suite against RC2 now. RC2 (September 1) is ABI-frozen, so what you test now is what ships on October 1. The failures you see are the migration work you have to do.
3. Grep for the removals. datetime.utcnow, __cached__, SetPointerType, and encoding= omissions on file opens are all one-line greps. The UTF-8 default is the one that will surface most in Windows desktop or batch-processing environments.
4. Check your dependency pins. As of RC1, only about 9.4 percent of the top 360 PyPI packages declared 3.15 support. numpy, requests, pytest, black, mypy, and sqlalchemy were ready. pandas, boto3, cryptography, pydantic, scipy, Flask, and click were not. If your project depends on any of the second list, you have two choices: pin to 3.14 until the library ships, or patch the specific test failure locally. The number will move fast; the byteiota RC1 coverage is a good baseline.
5. Treat the JIT as opt-in. You do not need it to get value from 3.15. The 8 to 9 percent is real but it requires enabling an experimental feature. Default off is the right choice for most production workloads, and the experimental status means the performance profile can still shift between 3.15 and 3.16.
For teams that ship language tooling on a regular cycle, Microsoft's TypeScript 7.0 native Go compiler is the closest parallel move, where a major release trades a mature codebase for a cleaner, faster implementation. The Python release cycle is more conservative, and 3.15 is the release where that conservatism pays off in feature density.
Conclusion
October 1 is the date to plan around: patch the August security release now, run your suite on RC2, and check the two dependencies that are most likely to block you. PEP 828 is a 3.16 feature, not a 3.15 one, so the async-generator work can wait a year. Subscribe to TekMag for follow-up coverage on the 3.15 final release day.
Frequently asked questions
<h3>Q: Should I upgrade to Python 3.15 right after release?</h3>
<p>Only if your test suite passes cleanly on RC2 and your dependencies declare 3.15 support. If any of your core libraries were not ready as of RC1, hold on 3.14 and re-check in a few weeks. The release cadence means you are not behind if you skip a version.</p>
<h3>Q: Do I get the 8 percent JIT speedup in 3.15 by default?</h3>
<p>No. The JIT is still off by default and marked experimental. You need a build or startup flag to enable it, and the 8 to 9 percent is a geometric mean on benchmark suites, not a guarantee for your workload. For most production code, treat it as opt-in.</p>
<h3>Q: Which security release should I patch to first?</h3>
<p>The August 12 batch: 3.12.14, 3.11.16, or 3.10.21 depending on your branch. The highest-severity item is CVE-2026-4224 (CVSS 8.6), a stack overflow in XML parsing that is a denial-of-service risk for any service ingesting untrusted XML. The 3.10 branch is also close to end of life, so plan a move to 3.11 or 3.12 on top of the patch.</p>
<h3>Q: What is the migration checklist for 3.15?</h3>
<p>Patch your current branch for the August security release, run your suite against RC2 now, grep for <code>datetime.utcnow</code> and missing <code>encoding=</code> arguments on file opens, and verify that your dependency pins declare 3.15 support. The UTF-8 default on Windows is the most likely source of failures.</p>
<h3>Q: When will <code>yield from</code> in async generators actually ship?</h3>
<p>PEP 828 is accepted for Python 3.16, which first releases in October 2027 under the PEP 602 12-month cycle. The PEP was resolved on August 3, 2026, so the implementation work is already underway on the feature branch. You do not need to rush for this one.</p>
References
- PEP 828, Supporting 'yield from' in asynchronous generators (peps.python.org)
- PEP 790, Python 3.15 Release Schedule (peps.python.org)
- Python 3.15.0 candidate 1 is here, Hugo van Kemenade (blog.python.org)
- Python 3.12.14, 3.11.16, and 3.10.21 are now available (blog.python.org)
- Python 3.15's JIT is now back on track (blog.python.org)
- Async Generators Get yield from and Other Python News for September 2026 (Real Python)
- Status of Python versions, PEP 790 (devguide.python.org)
- SUSE security update for python, SUSE-SU-2026:1417-1 (SUSE)
- Python 3.15 RC2: Lazy Imports, frozendict, and a Real Speed Boost (byteiota)
{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "Q: Should I upgrade to Python 3.15 right after release?", "acceptedAnswer": {"@type": "Answer", "text": "Only if your test suite passes cleanly on RC2 and your dependencies declare 3.15 support. If any of your core libraries were not ready as of RC1, hold on 3.14 and re-check in a few weeks. The release cadence means you are not behind if you skip a version."}}, {"@type": "Question", "name": "Q: Do I get the 8 percent JIT speedup in 3.15 by default?", "acceptedAnswer": {"@type": "Answer", "text": "No. The JIT is still off by default and marked experimental. You need a build or startup flag to enable it, and the 8 to 9 percent is a geometric mean on benchmark suites, not a guarantee for your workload. For most production code, treat it as opt-in."}}, {"@type": "Question", "name": "Q: Which security release should I patch to first?", "acceptedAnswer": {"@type": "Answer", "text": "The August 12 batch: 3.12.14, 3.11.16, or 3.10.21 depending on your branch. The highest-severity item is CVE-2026-4224 (CVSS 8.6), a stack overflow in XML parsing that is a denial-of-service risk for any service ingesting untrusted XML. The 3.10 branch is also close to end of life, so plan a move to 3.11 or 3.12 on top of the patch."}}, {"@type": "Question", "name": "Q: What is the migration checklist for 3.15?", "acceptedAnswer": {"@type": "Answer", "text": "Patch your current branch for the August security release, run your suite against RC2 now, grep for datetime.utcnow"}}, {"@type": "Question", "name": "Q: When will yield from", "acceptedAnswer": {"@type": "Answer", "text": "PEP 828 is accepted for Python 3.16, which first releases in October 2027 under the PEP 602 12-month cycle. The PEP was resolved on August 3, 2026, so the implementation work is already underway on the feature branch. You do not need to rush for this one."}}]}
Top comments (0)