Linux

Python 3.15 Released: Lazy Imports, UTF-8 Default, Faster JIT

Python 3.15 brings lazy imports, UTF-8 by default, frozendict, a faster JIT and a new sampling profiler.

12 October 2026  ·  5 min read  ·  Kalesh Krishnan

Python 3.15 Released: Lazy Imports, UTF-8 Default, Faster JIT

Python 3.15.0 was released on October 9, 2026. It is the yearly feature release, and the Python team says it includes more than 5,600 commits from over 1,000 contributors. A few of the changes help right away, such as faster startup and a sampling profiler that can attach to a running process. One change can break older code: UTF-8 is now the default text encoding. Below is what’s new, what could affect your existing applications, and how to test the new version without disturbing the Python your servers already use.

The headline features

Lazy imports (PEP 810)

The new lazy keyword marks an import as deferred. Python doesn’t load the module until your code first uses it. That helps command-line tools, management scripts and serverless functions, which often import large libraries they never touch on a given run.

lazy import json
lazy from decimal import Decimal

def export(data):
    # json is only loaded here, on first use
    return json.dumps(data)

Normal imports work exactly as before. Lazy imports only apply where you write the keyword, so you can add them one module at a time and measure the effect.

UTF-8 by default (PEP 686)

Python now uses UTF-8 by default. In practice, open() without an encoding argument now reads and writes UTF-8 on every platform. Before, it used the system locale. On most Linux servers this changes nothing, because the locale was already UTF-8. Windows hosts, minimal containers with a C or POSIX locale, and scripts that handle files in legacy code pages such as cp1252 or Latin-1 may behave differently.

New built-in types

  • frozendict (PEP 814): an immutable dictionary that keeps insertion order. If its keys and values are hashable, the frozendict is hashable too, so you can use it as a dict key, put it in a set or use it as a cache key.
  • sentinel (PEP 661): a standard way to create unique marker values. For example, it lets you tell “argument not given” apart from an explicit None, without the usual object() workarounds.

A faster experimental JIT

The JIT compiler is still experimental, but it has improved a lot. The release notes report a 7-8% geometric mean speedup on x86-64 Linux over the standard interpreter, and 11-12% on AArch64 macOS over the tail-calling interpreter. Other changes this release include clearer error messages, more colour in command-line output, comprehension unpacking (PEP 798) and package startup configuration files (PEP 829).

Changes that matter for operations

Profiling without restarts

The new profiling package (PEP 799) brings Python’s profiling tools together in one place. It includes Tachyon, a high-frequency sampling profiler. Tachyon can attach to a process that is already running, with no restart and no code changes. It can measure CPU time, wall-clock time or time spent holding the GIL, and it can produce flame graphs. If you have ever had to restart a slow production worker just to find out where it spends its time, this is the most useful change in the release.

Frame pointers on by default (PEP 831)

Python is now built with frame pointers enabled on supported platforms. As a result, system-level tools like perf and eBPF-based profilers can show complete native stack traces through the interpreter, without a special build.

Free-threading and platform builds

Free-threaded (no-GIL) builds now have a stable ABI (PEPs 803, 820 and 793). Library authors can ship one binary wheel for them instead of rebuilding it for every Python version. The official macOS installers now include free-threading support by default, and the official 64-bit Windows binaries use the tail-calling interpreter.

There is one known issue on macOS. On macOS 27.0, Tk-based GUI programs, including IDLE, may hang when a menu command opens a dialog. If your developers rely on tkinter tools, have them test before upgrading macOS.

How to try Python 3.15 safely

Don’t replace your distribution’s system Python. On RHEL, Rocky, AlmaLinux, Debian and Ubuntu, package managers and system tools depend on the Python version the distribution ships. Install 3.15 alongside it instead:

# With uv (any Linux distribution, macOS or Windows)
uv python install 3.15
uv venv --python 3.15 .venv
source .venv/bin/activate
python --version

# Or with pyenv
pyenv install 3.15.0
pyenv local 3.15.0

If you build from source, use make altinstall, not make install. That way /usr/bin/python3 isn’t overwritten.

Upgrade checklist

  1. Check your dependencies. Make sure the libraries you rely on, especially ones with C extensions, publish wheels for 3.15. Until they do, pip will try to build them from source.
  2. Run your tests in CI against 3.15. Add it to your test matrix alongside your current version, and turn on warnings with python -W error::DeprecationWarning to find deprecated calls.
  3. Look for file I/O that depends on the system locale. Search the code for open( calls that don’t pass an encoding argument, and test them with real data files. If a legacy job needs the old behaviour for now, set PYTHONUTF8=0 or run it with -X utf8=0, and plan a proper fix.
  4. Try lazy imports in your slowest-starting tools and time startup before and after.
  5. Benchmark before enabling the JIT. It is still experimental, so measure your own workload first.
  6. Update container base images and deployment scripts only after staging passes.

How TechProvidence can help

Upgrading Python on production servers involves more than installing a new interpreter. You have to keep the system Python intact, rebuild virtual environments, check native dependencies and roll the change through CI/CD without downtime. TechProvidence handles Python runtime upgrades, container and pipeline updates, and ongoing managed server care for Linux and cloud environments. If you want a planned move to Python 3.15, or help with older applications stuck on unsupported versions, contact us.

Should you upgrade now?

For new projects, starting on 3.15 makes sense. For existing production systems, test it in CI and staging first, and move once your dependencies support it. The UTF-8 default is the change most likely to cause trouble, so check that first. Tachyon and lazy imports are the features most likely to save you time.

Source: Python Insider

Running into something similar?

We look after Linux servers, control panels and virtualization for businesses every day. If an update, vulnerability or outage here affects you, we can help.