@blog
What’s new in Python 3.15
Python 3.15.0 was released on 9 October 2026. These are the main changes.
Tiffany Nguyen · 19 October 2026
frozendict
frozendict is a new built-in type that works like a dict but cannot be changed after it is created. It keeps insertion order, and it is hashable if all its keys and values are hashable. It is not a subclass of dict.
>>> a = frozendict(x=1, y=2) >>> a['z'] = 3 Traceback (most recent call last): ... TypeError: 'frozendict' object does not support item assignment
Modules such as copy, json, pickle and pprint accept it.
sentinel
sentinel is a new built-in for unique placeholder values, such as a default that means no argument was given. A sentinel stays the same object when copied, can be used in type hints with |, and can be pickled if it can be imported by module and name.
MISSING = sentinel("MISSING")
def next_value(default: int | MISSING = MISSING): ...Lazy imports
The new lazy keyword delays loading a module until it is first used, which can shorten start-up time.
lazy import json lazy from pathlib import Path
lazy is only allowed at module level. Using it inside a function, a class body or a try block raises SyntaxError. To make every import lazy without changing code, run Python with -X lazy_imports=all or set PYTHON_LAZY_IMPORTS=all.
Unpacking in comprehensions
* and ** now work in list, set and dict comprehensions and in generator expressions.
>>> [*L for L in [[1, 2], [3, 4], [5]]]
[1, 2, 3, 4, 5]
>>> {**d for d in [{'a': 1}, {'b': 2}, {'a': 3}]}
{'a': 3, 'b': 2}UTF-8 by default
When no encoding is given, Python now uses UTF-8 on every platform instead of the system locale. open("notes.txt") reads and writes UTF-8. To keep the old behaviour, set PYTHONUTF8=0 or run Python with -X utf8=0.
Profiling
The new profiling package holds Python’s profilers. profiling.tracing is the profiler from cProfile, which stays as an alias. profiling.sampling is a new sampling profiler called Tachyon. The profile module is deprecated and will be removed in Python 3.17.
Tachyon can run a script or module, or attach to a running process by its PID. It can measure wall-clock time, CPU time, time holding the GIL and time spent handling exceptions, and it supports async code. Results can be saved as pstats data, an HTML flame graph, a Firefox Profiler file or an HTML heatmap, or watched live in the terminal.
Error messages
More errors now suggest a fix. Method names from other languages point to the Python name, and calling a list method on a tuple suggests using a list.
>>> [1, 2, 3].push(4) Traceback (most recent call last): ... AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'? >>> 'hello'.toUpperCase() Traceback (most recent call last): ... AttributeError: 'str' object has no attribute 'toUpperCase'. Did you mean '.upper'? >>> (1, 2, 3).append(4) Traceback (most recent call last): ... AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
Python also suggests attributes on nested objects, such as .inner.area in place of .area, and suggests the right name when del is given a misspelled attribute.
TypedDict extra items
TypedDict takes two new class arguments. With closed=True, keys not listed in the class are not allowed. With extra_items=int, extra keys are allowed if their values are int.
class Movie(TypedDict, closed=True):
name: str
year: intJIT compiler
The experimental JIT compiler has been upgraded. On the pyperformance benchmarks it is 7–8% faster than the standard interpreter on x86-64 Linux, and 11–12% faster than the tail-calling interpreter on AArch64 macOS. Individual benchmarks range from about 15% slower to more than twice as fast.
Other changes
Packages can ship .start files that list pkg.mod:callable entries to run at start-up. They replace import lines in .pth files, which are now deprecated.
More output is in colour, including python --help, tab completion in the REPL, unraisable exceptions, and the command-line tools of modules such as argparse, sqlite3 and timeit.
For C extension authors, the new PyBytesWriter API builds a bytes object piece by piece.
The full list is in What’s new in Python 3.15.