Stack Signal.
Technical news & guides across AI, programming and the open-source world
SATURDAY, NOVEMBER 07, 2026 · 101 articles · RSS

Programming & Web DevOct 20, 2026558 words

Python 3.15 Ships: Lazy Imports, frozendict, and a Built-In Profiler

Python 3.15.0 landed on Friday, October 9 — about a week after the October 1 date in PEP 790, pushed back by a third release candidate. This is one of the most practical releases in years: a real answer to slow startup, two new built-in types, UTF-8 as the default encoding, and a profiler you can attach to a running process.

The lazy keyword (PEP 810)

Python imports a module the moment you import it, even when a CLI tool only touches one function from it. Lazy imports change that. Mark an import with lazy and Python defers loading until the name is first used:

lazy import json
lazy from pathlib import Path

lazy is a soft keyword, so existing code that uses it as a variable name keeps working. There are guardrails: lazy imports are only allowed at module scope, so lazy inside a function, class body, or try/except block raises a SyntaxError, and neither star imports nor __future__ imports can be lazy. For code that must still run on older Pythons, a module-level __lazy_modules__ list opts specific imports in. Or skip the keyword entirely: -X lazy_imports=all (or PYTHON_LAZY_IMPORTS) makes every import lazy, no source changes needed.

The implementation, by Pablo Galindo Salgado and Dino Viehland, is the pay-only-for-what-you-use answer to slow startups — the biggest win for command-line tools that import a dozen frameworks at boot.

Two new built-ins: frozendict and sentinel

PEP 814 adds frozendict, an immutable dict built-in — the long-missing sibling of frozenset. Handy for configuration constants and for sharing read-only mappings across threads without hoping nobody mutates them. PEP 661 adds sentinel, a real built-in type for "no value" markers, replacing the object() singleton trick that quietly breaks when the marker gets copied or pickled — the is comparison stops matching.

UTF-8 by default

Text files now decode as UTF-8 without you asking, the encoding the rest of the world already assumes. The PYTHONUTF8 environment variable still opts out for legacy projects. CPython also enables frame pointers wherever the platform supports them (PEP 831), so system-level profilers can unwind the stack reliably. Small changes, felt everywhere.

Tachyon: a profiler you attach (PEP 799)

profiling.sampling, named Tachyon, is a statistical profiler in the standard library. Because it samples rather than instruments, overhead is virtually zero, and it can attach to an already-running process and dump a profile without a restart. It understands threads and async tasks, and can profile at opcode level. PyCon US 2026 has a talk simply titled "Tachyon: Python 3.15's sampling profiler is faster than your code" — which is the point.

The rest of the bus

Windows 64-bit installers now run the tail-calling interpreter (15-20 percent faster than the old switch-based one, per the docs), and macOS binaries install free-threading support by default. Typing gains closed TypedDicts with extra_items (PEP 728) and typing.TypeForm. Comprehensions can unpack. There's a new math.integer module for integer-specific math.

3.15.0 arrived in 5,643 commits from 1,012 contributors, and the support runway is long: bugfix releases every two months for two years, then security-only updates until around October 2031. If slow startup is a sore spot in anything you build, the lazy-import story is the most interesting thing Python has shipped in a long time — and unlike most performance work, you can adopt it one import at a time.