Python 3.11 New Features — Core Concepts
Why Python 3.11 matters
Released in October 2022, Python 3.11 delivered on a promise: make Python significantly faster without breaking anything. But it also shipped several features that changed how developers handle errors and configure projects.
The Faster CPython project
Microsoft funded a team (led by Mark Shannon, with Guido van Rossum advising) to speed up CPython. The 3.11 results:
- 10–60% faster on the pyperformance benchmark suite, with an average of ~25%
- Zero code changes required — existing programs run faster automatically
- Key optimisations include: specialised bytecodes that adapt to runtime types, faster function calls, and lazy creation of exception tracebacks
This was the first phase of a multi-release plan (continuing in 3.12 and 3.13).
Fine-grained error locations (PEP 657)
Building on 3.10’s improved errors, 3.11 adds column-level highlighting in runtime tracebacks:
Traceback (most recent call last):
File "calc.py", line 4, in <module>
result = a["key"] + b.value / c
~~~~~~~~^~~
ZeroDivisionError: division by zero
The ~ and ^ characters pinpoint the exact sub-expression. This transforms debugging — instead of re-reading the entire line, you instantly see which operation failed.
Exception groups and except* (PEP 654)
When multiple operations can fail concurrently, you need to report multiple errors. ExceptionGroup bundles them:
eg = ExceptionGroup("batch failures", [
ValueError("bad input"),
ConnectionError("server down"),
TimeoutError("too slow"),
])
raise eg
except* selectively catches from the group:
try:
run_batch_jobs()
except* ValueError as eg:
for err in eg.exceptions:
log_validation_error(err)
except* ConnectionError as eg:
for err in eg.exceptions:
retry_connections(err)
Each except* clause runs independently — they don’t short-circuit. Unmatched exceptions propagate as a new (smaller) group. This is critical for:
asyncio.TaskGroup(also new in 3.11), which raisesExceptionGroupwhen child tasks fail- Retry frameworks that accumulate errors
- Test runners reporting multiple failures
asyncio.TaskGroup
A structured concurrency primitive that replaces the error-prone gather():
async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch_users())
tg.create_task(fetch_orders())
tg.create_task(fetch_inventory())
# All tasks completed or all cancelled on first failure
If any task raises, the remaining tasks are cancelled and all exceptions are bundled into an ExceptionGroup. No more silently lost exceptions from gather(return_exceptions=True).
tomllib — built-in TOML parser (PEP 680)
TOML (Tom’s Obvious Minimal Language) is the standard format for pyproject.toml. Now you can read it without third-party dependencies:
import tomllib
with open("pyproject.toml", "rb") as f:
config = tomllib.load(f)
print(config["project"]["name"])
Note: tomllib is read-only. For writing TOML, you still need tomli-w or tomlkit.
Self type (PEP 673)
Methods that return the current class can now express that cleanly:
from typing import Self
class Builder:
def set_name(self, name: str) -> Self:
self.name = name
return self
Before Self, you needed TypeVar bound to the class, which was verbose and error-prone with inheritance.
Other notable changes
StrEnumadded to theenummodule — enum members that are also strings- Variadic generics (
TypeVarTuple, PEP 646) — type variables that represent multiple types, enabling typed tensor shapes - Negative zero-cost exception handling —
tryblocks with no exception have zero overhead (previously there was a small cost)
Common misconception
“The 25% speedup means my web app is 25% faster.” The speedup varies widely by workload. CPU-bound pure Python code sees the biggest gains. I/O-bound applications (web servers waiting on databases/network) see less impact because the bottleneck isn’t Python execution speed.
The one thing to remember: Python 3.11 proved that Python could get dramatically faster without sacrificing compatibility — and exception groups gave async code the error handling it always needed.
See Also
- Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.
- Python 312 New Features Python 3.12 made type hints shorter, f-strings more powerful, and started preparing Python's engine for a world without the GIL.
- Python 313 New Features Python 3.13 finally lets multiple tasks run at the same time for real, added a speed booster engine, and gave the interactive prompt a colourful makeover.
- Python Exception Groups Python's ExceptionGroup is like getting one report card that lists every mistake at once instead of stopping at the first one.
- Python Free Threading Nogil Python has always had a rule that only one thing can happen at a time — free threading finally changes that, like opening extra checkout lanes at the grocery store.