Skip to main content
  1. Blog/

Python 3.12 — A Performance-Focused Release Worth Getting Excited About

·1045 words·5 mins
Osmond van Hemert
Author
Osmond van Hemert
Python Evolution - This article is part of a series.
Part : This Article

Python 3.12 is now at release candidate 2, and the final release is expected in October. I’ve been testing it against some of my projects, and I’m genuinely impressed. This isn’t a flashy release with headline-grabbing new syntax — it’s a disciplined, engineering-focused update that addresses real pain points. After thirty years of watching programming languages evolve, I can tell you: these are the releases that matter most.

The Performance Story Continues
#

The Faster CPython project, led by Mark Shannon and supported by Microsoft, is delivering on its promises. Python 3.11 gave us a 10-25% speedup, and 3.12 continues that trajectory with additional optimizations to the interpreter loop and object creation paths.

The most significant performance work in 3.12 is the implementation of PEP 669 — Low Impact Monitoring for CPython. This overhauls how debugging and profiling tools hook into the interpreter. Previously, having a debugger or profiler attached would slow down all code execution, even code that wasn’t being monitored. With PEP 669, monitoring has near-zero overhead for code that isn’t being actively watched.

If you’ve ever noticed your test suite running significantly slower under coverage.py, or your application getting sluggish when a profiler is attached, this is directly relevant. The new monitoring API means tools can be more surgical about what they instrument, and the interpreter doesn’t pay a tax just because a monitoring tool is loaded.

For those of us who routinely profile production systems, this is a meaningful quality-of-life improvement. I’ve always been cautious about running profilers in production precisely because of the performance overhead. PEP 669 could change that calculus.

Better Error Messages, Better Developer Experience
#

Python 3.10 introduced better error messages, and 3.11 expanded on them with fine-grained exception locations. Python 3.12 takes another step with improved suggestions for common mistakes. The interpreter now provides more helpful “did you mean?” suggestions for NameError, ImportError, and SyntaxError.

For example, if you type import datetime and then reference datetime.datatime.now(), the error message will now suggest datetime.datetime. These seem like small things, but they add up. I mentor junior developers regularly, and I can tell you that cryptic error messages are one of the biggest sources of frustration for people learning the language. Every improvement here lowers the barrier to entry.

The error messages for invalid escape sequences in strings have also been upgraded from DeprecationWarning to SyntaxWarning, which is a signal that these will become errors in a future release. If you have "\d+" in your regex strings without using raw strings (r"\d+"), now’s the time to clean those up.

Type System Improvements
#

Python’s gradual typing story continues to mature with 3.12. The headline feature is PEP 695, which introduces a new, cleaner syntax for type parameters. Instead of the somewhat clunky:

from typing import TypeVar

T = TypeVar('T')

def first(l: list[T]) -> T:
    return l[0]

You can now write:

def first[T](l: list[T]) -> T:
    return l[0]

This syntax also works for classes and type aliases:

type Vector[T] = list[T]

class Stack[T]:
    def push(self, item: T) -> None: ...
    def pop(self) -> T: ...

The type statement for type aliases (PEP 695) is cleaner and more intuitive than TypeAlias. If you’ve worked with generics in TypeScript, Rust, or Java, this syntax will feel immediately familiar. Python’s type system has been evolving rapidly, and this release makes it feel substantially more natural.

The No-GIL Future Takes Shape
#

Perhaps the most architecturally significant work in 3.12 is the foundation for PEP 684 — per-interpreter GIL. This allows multiple Python interpreters within the same process to have their own Global Interpreter Lock, enabling true parallelism for certain workloads.

This is distinct from the full “no-GIL” proposal (PEP 703), which Sam Gross has been developing and the Python Steering Council is evaluating. But PEP 684 is an important stepping stone. It enables parallelism through sub-interpreters without the ecosystem disruption of removing the GIL entirely.

For most Python developers, the GIL has been a known limitation that you work around with multiprocessing or async I/O. The per-interpreter GIL won’t change your daily workflow immediately, but it’s laying groundwork for a future where CPU-bound Python code can truly utilize multiple cores without the overhead of separate processes.

I’ve been following the GIL discussion for years, and what impresses me about the current approach is its pragmatism. Rather than a revolutionary change that breaks the entire C extension ecosystem, the CPython team is taking an incremental path. That’s the kind of engineering discipline that keeps a language healthy for decades.

Practical Migration Considerations
#

If you’re planning to upgrade to 3.12, here are the things I’d watch for:

Deprecated removals: Several long-deprecated modules have been removed, including distutils (use setuptools instead), asynchat, asyncore, and imp. If you’re maintaining older codebases, audit your imports before upgrading.

String escaping: The strengthened warnings about invalid escape sequences mean your CI might suddenly light up with warnings. Address them now rather than waiting for them to become errors.

f-string changes: F-strings in 3.12 have been reimplemented to remove several previous limitations. You can now nest quotes freely, use backslashes, and even include comments in multi-line f-strings. This is mostly additive, but if you had workarounds for the old limitations, you can simplify your code.

Typing: If you adopt the new type parameter syntax, your code will require 3.12+ to run. For libraries that need to support older versions, you’ll want to stick with the TypeVar approach for now.

My Take
#

Python 3.12 is a release that makes me optimistic about the language’s trajectory. After years of hearing “Python is too slow” and “the GIL makes Python useless for parallel work,” the CPython team is systematically addressing these criticisms without breaking the ecosystem.

The performance improvements are real and cumulative. The developer experience keeps getting better. The type system is maturing into something genuinely useful rather than just a bolted-on afterthought. And the GIL work suggests a future where Python’s concurrency story is competitive with languages that have always had it easier.

If you haven’t tested your projects against the release candidate, I’d encourage you to try it. The migration is typically smooth, and the benefits are tangible. Python remains one of the most productive languages for a huge range of tasks, and 3.12 makes it measurably better.

Python Evolution - This article is part of a series.
Part : This Article