RETRO

Software and AI · programming language · software · Windows, macOS, Linux

Python 3.15.0: lazy modules, frozen dicts and two patches in two weeks

Python 3.15.0: lazy modules, frozen dicts and two patches in two weeks
Image: publisher's press kit

No games, no graphics cards: this month the pages belong to a programming language. Python 3.15.0 came out on 9 October 2026, with Hugo van Kemenade as release manager. You might shrug it off as just another one of those releases that turn up every October and turn the page, but this time some of the changes reach into the code you write every day. Let me say up front what we're going on: the release page on python.org, the relevant PEP documents and the release notes. We didn't install it and measure anything ourselves.

Credits: Python 3.15.0. Python Software Foundation. Open source, free. Download from python.org.

Where does it install?

For Windows users the recommended route is now the Python install manager (you type py install 3.15 and you're done). If you want them, there are also 64-bit, 32-bit and ARM64 installers, plus embeddable packages. This time the 64-bit Windows builds ship with the tail-calling interpreter. That means the interpreter's inner loop is built in a way the compiler likes better. The release page doesn't give a separate speed figure for Windows.

On the macOS side there's an installer for 10.15 and later. free-threading (the build that runs without the GIL, the global interpreter lock) now gets installed by default. Linux folks get the source archive as usual (gzip and xz, with SHA-256 checksums and Sigstore signatures). What they're really waiting for, though, is their distribution's package. python.org doesn't ship binaries for Linux; the distributions have always done that. And there are embeddable packages for Android (aarch64 and x86_64) and an XCframework for iOS. Python on a phone: once upon a time you could only say that as a joke!

Now for the interpreter

Lazy imports (PEP 810). You import a module at the top of the file, but it isn't loaded until it's actually used. What matters is that this happens explicitly, because the programmer asks for it: nobody's code gets changed behind their back. The win is startup time. People who write command-line tools will love this most, because the tools that spend half a second loading forty modules when you type --help are now out of excuses.

frozendict (PEP 814). A built-in dictionary type that can't be changed. For years everybody had been faking this half-heartedly somewhere in their own code. Now it's part of the language. Quite a cute addition, if you ask me, and quite a late one.

sentinel (PEP 661). A way of saying "there's no value here" that's different from None. Until now, anyone who wanted to tell apart a function being given None from being given nothing at all made their own marker with object(). Now there's a built-in type for it.

Python 3.15.0: lazy modules, frozen dicts and two patches in two weeks
Image: publisher's press kit

Unpacking in comprehensions (PEP 798). You can unpack with * and ** inside list and dict comprehensions. Those double-for lines you write to flatten nested lists are going to get a lot easier to read.

UTF-8 as the default encoding (PEP 686). This might be the quietest change in the release, and the one with the biggest effect. When you opened a file with open() without naming an encoding, Windows used the system's local code page. On Turkish Windows that means cp1254. That's why a program written on Linux would trip over the letter "ş" on Windows and just freeze up. Now both sides use the same default. But watch out: if you have old programs that read files saved in the old code page without naming an encoding, this time they may blow up in the other direction. Before you switch, write the encoding= parameter out explicitly, and you're covered.

There are also package startup configuration files (PEP 829) and, as in every release, better error messages. For the last few versions Python's error messages have really been talking like a human being. Seeing a compiler that says "Did you mean this?" is still a bit strange for someone from the old generation.

JIT: 7–8 percent

The experimental JIT compiler has been updated. According to python.org, it gives a speed gain of around 7–8 percent as a geometric mean on x86-64 Linux. Not a number to get carried away with, but not one to sneer at either. And the word "experimental" is still sitting right there. So nobody expects you to run your production server on the JIT tomorrow morning. Don't forget that the figure is given only for x86-64 Linux, either. The release page doesn't say what happens on an ARM Mac or on Windows, and neither can we.

Standard library and types

The most interesting addition to the library is Tachyon (PEP 799): a high-frequency, statistical sampling profiler. The same PEP also brings a new profiling package that puts the profiling tools under one roof. Hunting for which profiler lives in which module is becoming history (well, let's hope). There are also more places that use colour in terminal output.

The type system gets typed extra items for TypedDict (PEP 728), TypeForm (PEP 747) and disjoint bases (PEP 800). These mostly concern people who write type checkers and people enforcing type discipline in big codebases. Someone who writes everyday scripts may not even notice these changes.

The C side: the real news is hiding here

For people who write extension modules, this is the most important line: a stable ABI for free-threaded builds (PEP 803, 820 and 793). Let me unpack what that means. The ABI (Application Binary Interface) defines how a compiled extension talks to the interpreter. A stable ABI means the same compiled package can run on several Python versions. The biggest obstacle to GIL-free Python catching on was that every extension had to be compiled separately for that build. That obstacle is now going away. There's also a new PyBytesWriter API (PEP 782) and a finalization guarantee that protects threads while the interpreter is shutting down (PEP 788).

On the build side, frame pointers are now on by default (PEP 831). That means system profilers like perf can read the Python stack correctly. Put that together with Tachyon and the hidden theme of this release becomes clear: Python is making it easier to measure its own slowness. I find that a pretty honest attitude.

Python 3.15.0: lazy modules, frozen dicts and two patches in two weeks
Image: publisher's press kit

(A small detour: the release page has a text adventure called "whatsnewt", written by Barry Warsaw. Type uvx --python 3.15 whatsnewt and you explore the release notes as a game. Turning a changelog into an adventure game is a very cute gesture for a language release. Anyway, back to our topic.)

The snags

Now for the less fun part. The release page gives a clear warning: on macOS 27.0, IDLE and other Tk-based applications may freeze. Progress is tracked in CPython under issue #158053. Anyone teaching Python with IDLE would do well to wait for that issue to close before their students update their Macs. (If the Linux folks are smiling as they read this line, fair enough, but don't laugh too hard. They're still waiting for their distribution's package too.)

The second snag shows up in the calendar. 3.15.1 came out on 21 October. 3.15.2, on the other hand, is a rushed security release. The python.org page says 25 October and PEP 790 says 26 October, most likely a time zone difference. This release stops the ssl module from trusting compromised eMudhra intermediate certificate keys (CVE-2026-115557). It closes a link issue in tarfile.tar_filter (CVE-2026-114583). http.cookiejar now rejects cookies with negative versions. On top of those there are about 130 more fixes from 70 contributors. Two maintenance releases within two and a half weeks of launch isn't a bad sign. Quite the opposite: it shows problems are being closed quickly. But the warning is plain: even the 3.15.0 page now says it has been superseded by 3.15.2. Do NOT install 3.15.0, install whatever the latest 3.15.x is!

How long is it supported?

According to PEP 790, a bugfix release will arrive roughly every two months. The last regular bugfix release, 3.15.14, is planned for 3 October 2028. After that come security fixes distributed as source only, running until roughly October 2031. A five-year lifespan, and free at that. For someone who comes from the days when you paid licence money for software, that generosity still catches you off guard. Don't forget the work that makes it possible, either: if you find a bug, report it, open an issue, send a PR.

Our verdict

Python 3.15 is less a release than an infrastructure investment. It doesn't have one single flashy feature. Lazy imports and the UTF-8 default make daily life easier. frozendict and sentinel pull into the language things people have done by hand for years. The free-threaded stable ABI removes the most concrete obstacle on the road to a GIL-free future. The JIT's 7–8 percent is a good start, but it's not yet clear what it's a promise of.

Should you switch? For a new project, yes, and with the latest 3.15.x. For an existing project, run your test suite in a virtual environment first. Look especially at the places that read files without naming an encoding. Don't take it to production without doing that. And before you switch, ALWAYS make a copy of your environment and your lock files. If you depend on IDLE on macOS 27, wait until the issue is closed.

That's all from Python for now. I'm curious which feature you'll use first, so write in. Those too lazy to write a letter can leave a comment, that works too. See you, take care!..

Sources

Contents · Issue 02 · October 2026