What's new, 9 min read, updated 13 October 2026

What's new in Python 3.15, and what it means for data work

Released on 9 October 2026, with lazy imports, UTF-8 by default, frozendict and a built-in sampling profiler. Here is what matters for data work.

PythonWhat's new
All guides and cheat sheets

Python 3.15 was released on 9 October 2026. It is a release full of practical improvements rather than one headline feature: scripts start faster, text files behave the same on every computer, and finding out why code is slow no longer needs extra tools. Here are the changes that matter most if you work with data, with examples you can try today.

Lazy imports: faster start-up for scripts and CLIs

PEP 810 adds a new lazy keyword. A lazy import binds the name straight away, but the module is only actually loaded the first time you use it.

Python
lazy import json
lazy from pathlib import Path

print("Starting up...")             # json and pathlib are not loaded yet

data = json.loads('{"key": "value"}')  # json is imported here, on first use
p = Path(".")                          # and pathlib here

Why it matters for data work: data scripts often import heavy libraries such as pandas, matplotlib or a cloud SDK, even when a particular run only needs one of them. With lazy imports, a command that only prints --help or processes a small file no longer pays to load everything. The total cost does not disappear for a program that uses every import; it simply moves to the first use.

  • lazy is only allowed at the top level of a module, not inside functions, classes or try blocks.
  • You can make every import lazy for a run with python -X lazy_imports=all, which is a quick way to measure the benefit before changing any code.

UTF-8 is now the default encoding

With PEP 686, open() uses UTF-8 when you do not pass an encoding, whatever the computer's language settings. Before 3.15, the same script could read a CSV correctly on a Mac and turn accented names into garbage on a Windows machine configured for another code page.

Python
# Python 3.15: UTF-8 on every operating system
with open("customers.csv") as f:
    header = f.readline()

Why it matters: fewer "it works on my machine" bugs with names like Zoë, Müller or Ecclesie Agazzi. If you genuinely need the old behaviour, run with PYTHONUTF8=0. The best habit is still to pass encoding="utf-8" explicitly in code that must also run on older versions.

frozendict: a built-in immutable dictionary

PEP 814 adds frozendict, a dictionary that cannot be changed and can therefore be hashed, used as a dictionary key or stored in a set.

Python
defaults = frozendict({"currency": "GBP", "decimals": 2})
custom = defaults | {"currency": "EUR"}   # creates a new frozendict

defaults["currency"] = "USD"
# TypeError: 'frozendict' object does not support item assignment

It is ideal for configuration and lookup tables that should never change by accident while a pipeline runs. Note that frozendict is not a subclass of dict, so code that checks isinstance(x, dict) should check for collections.abc.Mapping instead.

Unpacking inside comprehensions

PEP 798 lets you use * and ** inside comprehensions, which makes flattening lists and merging dictionaries much easier to read.

Python
batches = [[1, 2], [3, 4], [5]]
rows = [*batch for batch in batches]          # [1, 2, 3, 4, 5]

configs = [{"region": "UK"}, {"currency": "GBP"}, {"region": "IT"}]
merged = {**c for c in configs}               # {'region': 'IT', 'currency': 'GBP'}

A built-in sampling profiler

PEP 799 adds a new profiling package. profiling.tracing is the familiar deterministic profiler (cProfile still works as an alias), and profiling.sampling is a new low-overhead sampling profiler that can attach to a process that is already running, without changing its code.

Terminal
# Profile a script from the start
python -m profiling.sampling run my_pipeline.py

# Or attach to a long-running job by process ID
python -m profiling.sampling attach 12345

Why it matters: when a nightly job suddenly takes three hours instead of thirty minutes, you can now attach to it and see where the time goes, with flame graphs and a live view, using only the standard library.

A faster (still experimental) JIT

The experimental JIT compiler received major upgrades. The core team reports average speed-ups of about 7 to 8% over the standard interpreter on Linux x86-64, and 11 to 12% on Apple silicon Macs. It is still off by default; you can try it with PYTHON_JIT=1 on builds that include it. On Windows, the python.org installers also gained a faster interpreter design.

The free-threaded (no-GIL) build keeps the status it gained in 3.14: officially supported, but optional and installed separately. A new stable ABI for free-threaded builds (PEP 803) makes it easier for libraries to publish wheels for it, which is what most data libraries are waiting for.

Smaller changes worth knowing

  • sentinel (PEP 661) is a new built-in for creating unique "no value given" markers, such as MISSING = sentinel("MISSING"), so a default of None no longer has to mean two things.
  • Friendlier errors: calling [1, 2, 3].push(4) now suggests append, and similar hints cover habits from JavaScript and Java.
  • Typing: TypedDict can describe extra keys (PEP 728), which helps when typing JSON from APIs.
  • re.prefixmatch() is a clearer name for re.match(), which only matches at the start of a string.
  • The old profile module is deprecated and will be removed in Python 3.17.

Should you upgrade?

  • New projects and personal scripts: try it now. With uv, it is one command: uv python install 3.15.
  • Production pipelines: wait until pandas, NumPy, your database drivers and cloud SDKs publish 3.15 wheels, usually within a few weeks of release. Test in a branch, then pin the version.
  • Check two things first: code that relied on a non-UTF-8 default encoding, and checks like isinstance(x, dict) that might now receive a frozendict.

Still on an older version? What's new in Python 3.14 covers the previous release, including official free-threading and template strings.

Sources: the official "What's New in Python 3.15" documentation on python.org and the Python 3.15 release coverage. Always check the official page and your libraries' release notes before upgrading production code.

Alessandro Ecclesie AgazziWritten by Alessandro Ecclesie Agazzi, analytics engineer in London. Updated 13 October 2026. About me