Skip to main content
  1. Blog/

Python 3.12 Is Here — Performance, Developer Experience, and What Matters

·917 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 was officially released on October 2nd, and after spending a few days putting it through its paces, I think this is one of the most practically impactful releases in recent memory. Not because of any single headline feature, but because the cumulative improvements address real pain points that Python developers deal with every day.

The release notes are extensive, but let me focus on what actually matters for working developers.

Performance: The Steady March Forward
#

The CPython team has continued the performance work that started with the Faster CPython project initiated by Mark Shannon and backed by Microsoft. Python 3.12 delivers another round of improvements, building on the gains from 3.11.

The comprehension inlining optimisation is a nice touch — list comprehensions no longer create a separate frame, which reduces overhead. It’s the kind of change that doesn’t sound dramatic but adds up across a codebase that leans heavily on Pythonic idioms.

More significantly, the work on the specialising adaptive interpreter continues. The interpreter now handles more bytecode patterns efficiently, and the startup time improvements are noticeable if you’re running lots of short-lived Python processes — think CLI tools, serverless functions, or test suites.

I ran some informal benchmarks on a data processing pipeline I maintain, and saw roughly 5-8% improvement over 3.11 without changing any code. Your mileage will vary, but free performance is free performance.

Per-Interpreter GIL: Laying the Groundwork
#

This is the feature that has the most long-term significance, even though most developers won’t use it directly yet. Python 3.12 introduces per-interpreter GIL as a build-time option through PEP 684.

For those unfamiliar with the pain: Python’s Global Interpreter Lock (GIL) has been the bane of CPU-bound multithreaded code for decades. The per-interpreter GIL means that separate sub-interpreters can now run truly in parallel, each with their own lock.

The caveat is that this is primarily a C-API feature right now. There’s no convenient Python-level API for sub-interpreters with separate GILs yet — that’s expected to come in future releases. But the foundation is being laid, and it’s being laid carefully, which I appreciate.

Having worked with Python’s threading limitations since the late 1990s, I can say that the approach the core team is taking — incremental, backward-compatible, carefully tested — is exactly right. The GIL can’t be ripped out overnight without breaking half the C extension ecosystem.

Better Error Messages Continue to Shine
#

Python 3.11 made a huge leap in error message quality, and 3.12 continues the trend. The improvements to NameError suggestions are particularly welcome — if you mistype a variable name, Python now suggests corrections from a broader context, including module-level names and builtins.

The improved SyntaxError messages for common mistakes are also excellent. I’ve watched junior developers on my teams spend twenty minutes debugging what turns out to be a missing colon or an incorrect indentation. Every improvement in error messaging directly translates to developer productivity.

This might seem like a small thing compared to performance numbers, but I’d argue it’s one of the most impactful changes for the community. Python’s role as a teaching language and as a first language for many developers makes error message quality a genuine strategic feature.

Type Parameter Syntax (PEP 695)
#

The new type parameter syntax is a significant quality-of-life improvement for anyone using Python’s type system. Instead of the somewhat awkward TypeVar approach:

from typing import TypeVar
T = TypeVar('T')

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

You can now write:

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

This brings Python’s generic syntax closer to what developers expect if they’ve used generics in TypeScript, Java, or C#. The type statement for type aliases is similarly clean:

type Vector = list[float]
type Matrix[T] = list[list[T]]

I’ve been a gradual convert to Python’s type system over the past few years. It’s not perfect, and runtime enforcement is still largely absent without third-party tools, but for documentation, IDE support, and catching bugs early with mypy or pyright, it’s become indispensable on larger codebases. PEP 695 removes one of the last rough edges.

Removed Deprecated Modules
#

Python 3.12 removes a batch of long-deprecated modules including distutils, asynchat, asyncore, and several others. The distutils removal is the one most likely to bite people — if you have old setup.py files that import from distutils, it’s time to migrate to setuptools or another modern build backend.

This is healthy housekeeping. Python’s standard library has accumulated cruft over the decades, and clearing it out reduces maintenance burden and confusion for newcomers.

My Take
#

Python 3.12 is a solid release that continues the trajectory the core team has been on: faster runtime, better developer experience, and a more capable type system. There’s no single “must upgrade immediately” feature, but the cumulative effect is compelling.

My recommendation: start testing your projects against 3.12 now. If you’re still on 3.9 or 3.10, consider skipping straight to 3.12 — the performance improvements alone justify the effort, and the error message improvements will make your whole team more productive.

The per-interpreter GIL work is the one to watch for future releases. If the Python team can deliver a usable API for true parallelism in 3.13 or 3.14, it could fundamentally change how we think about Python for CPU-bound workloads. For now, it’s a promising foundation.

Python continues to be the language that meets you where you are. And with 3.12, it meets you a little faster and with better error messages when you take a wrong turn.

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