Python 3.15 Is Out: What's New and How to Update
Python 3.15.0 is officially available today, bringing lazy imports, a frozendict type, UTF-8 by default, and a new profiling package. Here's what changed and how to upgrade.

Python 3.15.0 is officially out. The Python core development team released the final build on October 9, 2026, exactly on the schedule set out in PEP 790, and it's available now for Windows, macOS, and source builds from python.org. The headline changes are explicit lazy imports, a new immutable frozendict type, unpacking inside comprehensions, UTF-8 as the default text encoding, and a standalone profiling package with a high-frequency sampling profiler called Tachyon. Below is a rundown of what actually changed, pulled from the official release notes, and a straightforward path to updating.
Python 3.15.0 Is Officially Released
After months as a release candidate, Python 3.15.0 moved to final status today. The official release page lists October 9, 2026 as the release date, with installers for Windows (64-bit) and macOS, plus the source tarball for Linux and other Unix systems that build from source. This is the first stable release in the 3.15 line, meaning it now receives full bugfix support, and it starts the clock on 3.15's roughly two-year window of active maintenance before it moves to security-only fixes.
This follows directly from Pandromeda's earlier coverage of the scheduled October 9 release date. That piece covered what was planned; this one covers what actually shipped and how to get it running.
The Biggest Language Changes
Several of 3.15's changes touch how Python code is written and imported, not just how fast it runs.
- Explicit lazy imports (PEP 810). A new
lazysoft keyword lets you writelazy import jsonorlazy from pathlib import Pathat module scope. The module isn't actually loaded until the first time an attribute on it is accessed, which can meaningfully cut startup time for programs that import a lot of modules they don't always use. It's opt-in: nothing changes unless you use the keyword, pass-X lazy_imports, or set thePYTHON_LAZY_IMPORTSenvironment variable. Wildcard lazy imports (lazy from module import *) and lazy__future__imports are disallowed and raise aSyntaxError. - Unpacking inside comprehensions (PEP 798). The
*and**unpacking operators now work directly inside list, set, dict, and generator comprehensions, including async ones.[*row for row in rows]flattens a list of lists without a separate helper function or nested loop. - UTF-8 as the default text encoding (PEP 686). Calls to
open()and other text I/O that don't specify anencodingargument now default to UTF-8 everywhere, rather than falling back to whatever the operating system's locale happens to be. This mainly affects Windows, where the previous locale-dependent default was a long-running source of "works on my machine" encoding bugs. Code that needs the old behavior can setPYTHONUTF8=0or pass-X utf8=0. frozendict, a built-in immutable mapping (PEP 814).frozendictis hashable when its keys and values are hashable, compares equal regardless of insertion order, and is accepted byjson,pickle,copy, andpprint, among other standard library modules. It inherits directly fromobject, not fromdict.sentinel, a built-in for unique marker values (PEP 661). Sentinel objects get a readablerepr(), keep their identity throughcopy/deepcopy, and work with the|union operator in type hints — replacing the common_SENTINEL = object()pattern with something the standard library understands natively.
Smaller syntax changes include unary + now being valid in match literal patterns (mirroring the existing support for unary -), __slots__ support for tuple subclasses, and the ability to declare __dict__ or __weakref__ via __slots__ on any class. The built-in slice type is also now generic and subscriptable.
Performance and Interpreter Changes
3.15 continues the multi-release push (started with the 3.11–3.13 adaptive interpreter and 3.13's experimental JIT) toward a faster CPython, with several changes aimed at profiling and native performance rather than headline throughput numbers:
- Frame pointers on by default (PEP 831). On supported platforms, CPython is now built with
-fno-omit-frame-pointer. This makes native stack traces from tools likeperfand eBPF-based profilers reliable without a special debug build, which matters for anyone profiling Python services in production. - Startup configuration via
.startfiles (PEP 829). Packages can now register entry points in the formpkg.mod:callablethat run automatically at interpreter startup. At the same time, the older trick of putting bareimportlines in.pthfiles is now silently deprecated. - Platform-specific build changes. Official Windows 64-bit binaries now use the tail-calling interpreter build, and official macOS binaries ship with free-threading support installed by default, continuing the free-threaded CPython work introduced in 3.13.
The official What's New in Python 3.15 document does not publish specific benchmark percentages for this release, so treat any such numbers you see elsewhere with some skepticism until you've measured your own workload.
A New Profiling Package, Plus the Tachyon Sampler
One of the more practically useful additions is a dedicated profiling package (PEP 799), which splits profiling into two pieces: profiling.tracing, the deterministic profiler moved over from cProfile (which remains available as an alias), and profiling.sampling, a brand-new statistical sampling profiler nicknamed Tachyon.
Tachyon can attach to an already-running process and sample it at up to 1,000,000 Hz without requiring any code changes or restart. It supports wall-clock, CPU, GIL-contention, and exception sampling modes, and can export results as pstats data, flamegraphs, Gecko profiles, or heatmaps, with live and async-aware modes for inspecting running asyncio applications. For teams that have been reaching for third-party samplers to profile production Python services without the overhead of a tracing profiler, this folds that capability into the standard library.
The older top-level profile module is now deprecated and is scheduled for removal in Python 3.17, so projects still importing it directly should plan a move to the profiling package.
Typing: TypedDict, TypeForm, and Disjoint Bases
The typing system picked up several refinements in 3.15, continuing the pattern of each release tightening up static-typing edge cases that mypy, pyright, and other checkers have to handle:
- Typed extra items in
TypedDict, letting you specify a type for keys beyond the explicitly declared ones instead of falling back toAny. TypeForm, a way to annotate values that represent type expressions themselves (for example, a variable that holdsint | stras a runtime value, used by validation and serialization libraries).- Disjoint bases, giving the type system a clearer way to reason about classes that intentionally cannot share a common instance.
These are primarily relevant to library authors and anyone leaning heavily on static type checking; they don't change runtime behavior for typical application code.
Standard Library and C API Highlights
Beyond the headline items, a long list of smaller library changes landed in 3.15:
base64andbinasciigainpadded,wrapcol,ignorechars, andcanonicalparameters, plus new Base32, Ascii85, Base85, and Z85 encoding functions.subprocess.Popen.wait(timeout=...)now uses event-driven waiting (pidfd/pollon Linux,kqueueon BSD and macOS) instead of polling in a loop.json.load()/loads()gain anarray_hookparameter; combined withfrozendictas theobject_pairs_hook, it's now possible to deserialize JSON into fully immutable data structures.tomllibnow supports TOML 1.1.0.ssladdsset_groups(),set_ciphersuites(), and new signature-algorithm configuration methods.bytearray.take_bytes()returns abytesobject without copying the underlying buffer.re.prefixmatch()is added as a clearer-named alternative tore.match(), which is now softly discouraged in favor of the new name.- Colorized output extends to
argparse,ast,calendar,difflib,http.server,pickletools,sqlite3,timeit,tokenize, andpython --help. - A new top-level
math.integermodule groups mathematical functions specifically for integer arguments. - On the C API side, 3.15 adds a stable ABI for free-threaded builds (
abi3t), a newPyBytesWriterAPI for buildingbytesobjects, and interpreter guards that protect C API calls from running during interpreter finalization.
Error messages also got another pass: AttributeError can now suggest nested attributes (for example, hinting at .inner.area when you typed .area), and common method names from other languages produce targeted hints — calling .push() on a list suggests .append(), and calling .put() on a dict suggests the correct d[k] = v syntax.
| Area | What changed in 3.15 | Reference |
|---|---|---|
| Imports | Explicit lazy import keyword for deferred module loading | PEP 810 |
| Syntax | */** unpacking allowed inside comprehensions | PEP 798 |
| Text I/O | UTF-8 is now the default encoding everywhere, including Windows | PEP 686 |
| Built-in types | New frozendict (immutable dict) and sentinel types | PEP 814 / PEP 661 |
| Profiling | New profiling package with the Tachyon sampling profiler | PEP 799 |
| Native performance | Frame pointers on by default for reliable native stack traces | PEP 831 |
| Security | tarfile fixes for five CVEs affecting extraction and symlinks | See Security section below |
| Deprecated | profile module (removal in 3.17), import lines in .pth files | Changelog |
Security Fixes in tarfile
The release notes list five tarfile-related CVE fixes bundled into 3.15:
- CVE-2025-4138:
data_filter()now normalizes symlink targets to prevent path traversal during extraction. - CVE-2024-12718:
extractall()no longer applies directory attribute fixes when a directory entry was actually replaced by a different kind of file. - CVE-2025-4330:
extract()/extractall()re-apply the extraction filter when substituting links with file copies, raising a newLinkFallbackErrorif that fails. - CVE-2025-4435: Members rejected by a filter are no longer extracted even when
errorlevelis set to 0. - CVE-2025-4517: A new
os.path.realpath(strict=os.path.ALLOW_MISSING)option was added to support safer path resolution.
None of these require code changes to benefit from — they're fixed at the standard library level once you're running 3.15 — but if your project extracts untrusted archives, it's a solid reason to prioritize the update.
Deprecations and Removals to Know About
A few things that used to work now emit warnings or have been removed outright:
- The
profilemodule is deprecated and will be removed in Python 3.17; use the newprofilingpackage instead. - Bare
importlines inside.pthfiles are now silently deprecated in favor of the new.startfile mechanism. - The
__cached__module attribute has been removed; use__spec__.cachedinstead. - The
PyGILState_*C API functions are soft-deprecated as part of the free-threading transition. re.match()is softly discouraged in favor of the new, more clearly namedre.prefixmatch().
As always with a .0 release, the full list of removed and deprecated APIs is longer than a single article can cover — check the official changelog if you maintain a large codebase before upgrading production systems.
A Caveat for macOS Users
The official release notes flag a specific interaction issue: on macOS 27.0, Tk-based applications — including IDLE, Python's bundled editor — may hang when opening certain dialogs. Python.org's guidance is to hold off on upgrading to macOS 27.0 if you rely on Tk-based tools until a workaround lands. This is an OS-level interaction issue, not a defect introduced by Python 3.15 itself, but it's worth knowing before you update both your OS and your Python version in the same sitting.
- Download the installer for your platform from python.org/downloads (Windows 64-bit
.exe, macOS.pkg, or the source tarball for Linux/Unix). - Keep your existing Python installation in place — installers for new minor versions install side-by-side rather than overwriting.
- Recreate virtual environments against the new interpreter (
python3.15 -m venv .venv) rather than trying to upgrade an existing one in place. - Reinstall dependencies inside the new environment and run your test suite before switching any production workload over.
- If you build CPython from source,
./configure,make, andmake installagainst the 3.15.0 source tarball as usual.
How to Update to Python 3.15
Updating is the same process as any other Python minor-version release:
- Windows: download the 64-bit installer from the Python 3.15.0 release page linked above and run it. Python's own install manager, distributed as an
.msixpackage, can also manage multiple installed versions side by side. - macOS: download the
.pkginstaller from the same release page. See the python.org macOS downloads page for platform-specific notes, and keep the Tk/IDLE caveat above in mind if you're also on, or planning to move to, macOS 27.0. - Linux and other Unix systems: most distributions package Python separately from upstream and may not carry 3.15 yet; building from the official source tarball on the release page is the most direct way to get it immediately, following the standard
./configure && make && make installprocess. - Existing projects: new Python versions install alongside older ones rather than replacing them, so there's no rush to migrate everything the same day. Create a fresh virtual environment with the 3.15 interpreter, reinstall your dependencies into it, and run your test suite before pointing anything important at it.
If you maintain a published package, it's also worth checking that your classifiers and CI matrix are updated to cover 3.15, particularly if you rely on C extensions — the free-threading and stable-ABI changes in this release are most relevant to compiled extension modules rather than pure-Python code.
Frequently Asked Questions
When was Python 3.15 released? Python 3.15.0 was released on October 9, 2026, per the official python.org release page.
What's the single biggest change in this release? There isn't one standout change so much as a cluster of them: explicit lazy imports (PEP 810), UTF-8 becoming the default text encoding (PEP 686), and the new immutable frozendict type (PEP 814) are the three most likely to affect everyday code.
How do I update to Python 3.15? Download the Windows or macOS installer from python.org, or build from the source tarball on Linux/Unix. New versions install side by side with older ones, so create a fresh virtual environment with the 3.15 interpreter rather than upgrading an existing one in place.
Does Python 3.15 remove anything I might rely on? The __cached__ module attribute has been removed, the profile module is deprecated ahead of removal in 3.17, and bare import lines in .pth files are now deprecated. Check the official changelog before upgrading a large codebase.
Is there a known issue with Python 3.15 on macOS? The release notes warn that Tk-based applications, including IDLE, may hang when opening dialogs on macOS 27.0, and recommend holding off on that OS upgrade until a fix is available.
What's Next
Python 3.15.0 starts its support clock today; expect the first bugfix release, 3.15.1, within the next couple of months as early adopters report issues, following the cadence set by prior releases. Python 3.14 continues to receive bugfix support in the meantime, so there's no urgency to move production systems off it immediately. If you haven't already, the official What's New in Python 3.15 page linked above is the authoritative reference for every change mentioned here, with far more detail on each item than fits in a news roundup. For background on how this release's date was set, see Pandromeda's earlier coverage of the October 9 release schedule, and if you're also updating your editor alongside your interpreter, our recent look at what's new in VS Code covers the editor side of a typical Python developer's toolchain.
Frequently asked questions
When was Python 3.15 released?
Python 3.15.0 was released on October 9, 2026, according to the official python.org release page.
What's the single biggest change in Python 3.15?
There isn't one standout change so much as a cluster of them: explicit lazy imports (PEP 810), UTF-8 becoming the default text encoding (PEP 686), and the new immutable frozendict type (PEP 814) are the three most likely to affect everyday code.
How do I update to Python 3.15?
Download the Windows or macOS installer from python.org/downloads, or build from the source tarball on Linux/Unix. New versions install side by side with older ones, so create a fresh virtual environment with the 3.15 interpreter rather than upgrading an existing one in place.
Does Python 3.15 remove anything I might rely on?
The __cached__ module attribute has been removed, the profile module is deprecated ahead of removal in Python 3.17, and bare import lines in .pth files are now deprecated. Check the official changelog before upgrading a large codebase.
Is there a known issue with Python 3.15 on macOS?
Yes. The release notes warn that Tk-based applications, including IDLE, may hang when opening dialogs on macOS 27.0, and recommend holding off on that OS upgrade until a workaround is available.
Sources
- Python 3.15.0 official release pagepython.org
- What's New in Python 3.15 (docs.python.org)docs.python.org
- Python 3.15.0 full changelogdocs.python.org
- PEP 790 - Python 3.15 Release Schedulepeps.python.org
- PEP 799 - The profiling packagepeps.python.org
Felix Moreau writes Pandromeda's software coverage and how-to guides. He covers Windows, macOS and Linux updates, the apps people rely on, emulators and developer tools, and turns official documentation into clear, numbered steps that work on the current version.

