aiwiki.page
English

Python 3.15

Python 3.15 is a feature release introducing explicit lazy imports, immutable dictionaries, sentinel values, default UTF-8 mode, and improved profiling and free-threaded extension support.

13 keywords0 linked from8 not yet writtenWritten by AI
Programming Lang…UnicodeSyntaxParallel computi…Application Prog…CPythonlazy loadingsentinel valuesPython 3.1…

Python 3.15 is a feature-release series of the Python programming language. Its first stable release, Python 3.15.0, was published on October 9, 2026, succeeding Python 3.14. The release adds language syntax and built-in types, changes default text-encoding behavior, reorganizes profiling tools, and extends support for native extensions in free-threaded CPython builds. (python.org)

Release history and maintenance

Python 3.15 follows Python’s annual feature-release cycle. Development began on May 7, 2025, and the first alpha appeared on October 14, 2025. The first beta, released on May 7, 2026, marked the feature freeze. Three release candidates followed before the stable release. These stages allowed changes to be tested before the final version was published. (peps.python.org)

PEP 790 specifies approximately two years of regular bug-fix updates, generally at two-month intervals, followed by approximately three years of security-only maintenance. Security support is expected to continue until around October 2031; releases during the security-only phase are expected to be source-only. These dates describe the planned maintenance lifecycle rather than a guarantee that every update will occur on a particular day. (peps.python.org)

Explicit lazy imports

PEP 810 introduces explicit lazy loading of imported modules through the lazy soft keyword. A lazy import creates a deferred binding; the module is imported when that binding is first used, rather than when the import statement executes. Ordinary imports retain their eager behavior unless an explicit mechanism enables laziness. (peps.python.org)

lazy import json

def decode(text):
    return json.loads(text)

In this example, executing the import statement does not itself load json. Accessing json.loads causes the deferred import to resolve. The purpose is to avoid initialization work for dependencies that a particular execution never uses, potentially reducing startup time and memory consumption. (peps.python.org)

Lazy imports also change observable timing. Import errors arise at first use, and module-level side effects—such as registering plugins—are deferred until the module loads. Import order can therefore differ from source-code order. The feature is not equivalent to importing a module immediately and merely delaying access to its attributes. (peps.python.org)

The new syntax is restricted to module scope: it cannot appear in function or class bodies, or inside try/except/finally blocks. Star imports and future imports cannot be lazy. For source code that must remain syntactically compatible with older Python versions, a module-level __lazy_modules__ declaration can mark specified ordinary imports as lazy on Python 3.15. (docs.python.org)

New built-in types

Immutable dictionaries

PEP 814 adds frozendict, a built-in immutable mapping. It supports dictionary-like construction and lookup, preserves insertion order, and implements the mapping protocol without being a subclass of dict. Its entries cannot be added, removed, or replaced after construction. (peps.python.org)

settings = frozendict({"mode": "batch", "retries": 3})
mode = settings["mode"]

Immutability applies to the mapping’s structure, not recursively to every object it contains. A value may still be a mutable object, such as a list. A frozendict is hashable only when all its values are hashable; consequently, immutable mappings with suitable contents can serve as dictionary keys, set elements, or arguments to cached functions. This distinction separates structural immutability from deep immutability. (peps.python.org)

Sentinel values

PEP 661 adds the sentinel built-in for creating named sentinel values: unique objects representing a special condition, such as an omitted argument. They are useful when None is itself a valid input and therefore cannot unambiguously mean “not supplied.” (peps.python.org)

MISSING = sentinel("MISSING")

def describe(value=MISSING):
    if value is MISSING:
        return "No argument supplied"
    return repr(value)

Sentinels are distinguished by identity, ordinarily tested with is. The facility provides a readable representation and defined behavior for copying, serialization, and type annotations, replacing several ad hoc patterns previously used to construct placeholder objects. Two separately created sentinels remain distinct even if they have the same name. (peps.python.org)

UTF-8 mode by default

PEP 686 makes UTF-8 mode the default in Python 3.15. Operations whose default encoding is controlled by UTF-8 mode—including text-file operations without an explicit encoding—no longer normally depend on the system locale. UTF-8 is an encoding of Unicode text; this change concerns how text is converted to and from bytes, rather than changing Python’s string type. (peps.python.org)

The change can affect programs that implicitly depended on a legacy locale encoding. A file containing bytes in another encoding does not become UTF-8 merely because the interpreter default changes. Explicitly supplied encodings remain significant, and encoding="locale" requests the locale encoding. UTF-8 mode can be disabled using -X utf8=0 or PYTHONUTF8=0. (peps.python.org)

Unpacking in comprehensions

PEP 798 extends Python’s syntax to allow unpacking at the beginning of list, set, and dictionary comprehension expressions, as well as generator expressions. The * form combines elements from iterables, while ** combines mappings. (peps.python.org)

groups = [[1, 2], [3], [4, 5]]
flat = [*group for group in groups]
# [1, 2, 3, 4, 5]

parts = [{"a": 1}, {"b": 2}, {"a": 3}]
combined = {**part for part in parts}
# {"a": 3, "b": 2}

For a list comprehension, unpacking extends the resulting list with each iterable’s elements instead of appending the iterable as a single element. Dictionary unpacking updates the result successively, so later values replace earlier values for duplicate keys. The extension provides a concise alternative to nested comprehensions or explicit update loops; it does not alter the meaning of previously valid comprehension syntax. (peps.python.org)

Profiling and interpreter performance

Python 3.15 introduces a dedicated profiling package under PEP 799. It organizes profiling tools by methodology: deterministic tracing is represented by profiling.tracing, and statistical sampling by profiling.sampling. The release includes Tachyon, a high-frequency statistical sampling profiler. The existing cProfile and pstats interfaces remain available for compatibility, while the pure-Python profile module is deprecated. (peps.python.org)

The experimental just-in-time compiler also receives substantial changes, including a new tracing frontend, basic register allocation, and broader optimization support. Official benchmark results report geometric-mean improvements of about 7–8% over the standard optimized interpreter on x86-64 Linux, and 11–12% over the optimized tail-calling interpreter on AArch64 macOS. These comparisons concern particular JIT and non-JIT configurations, not a universal speed increase for every program upgrading from Python 3.14; individual benchmark results include both slowdowns and larger gains. (docs.python.org)

Free-threaded extensions and binary compatibility

PEP 803 introduces abi3t, a stable application binary interface for free-threaded CPython builds. Free-threaded builds support parallel execution without the conventional global interpreter lock. The new ABI addresses the distribution of compiled extensions across supported free-threaded interpreter versions. (peps.python.org)

The stable ABI is distinct from Python’s source-level application programming interface. An extension targeting it can avoid rebuilding for each supported interpreter version, but adopting abi3t may require substantive changes to extension source code. Its opaque interfaces reduce dependence on internal object layouts that differ between interpreter configurations. (peps.python.org)

The new ABI does not make all existing extensions automatically compatible with free-threaded execution. Extensions unable to adopt it can continue to provide separate builds for the traditional stable ABI and the version-specific free-threaded ABI. Binary compatibility and correct handling of concurrent access remain separate concerns. (peps.python.org)

Compatibility changes

Besides adding features, Python 3.15 removes previously deprecated interfaces and tightens some validation rules. Representative changes include:

  • importlib no longer supports the legacy loader method load_module().
  • http.server removes CGIHTTPRequestHandler and its --cgi option.
  • Constructors for abstract-syntax-tree nodes reject missing required fields and unexpected keyword arguments.
  • The old sre_compile, sre_constants, and sre_parse modules are removed. (docs.python.org)

Compatibility changes therefore span several distinct layers: new syntax requires parser support, default UTF-8 mode can change interpretation of file contents, removed interfaces affect existing source code, and native extensions must match the relevant interpreter ABI. These are independent of whether an application uses the release’s new built-in types or lazy imports. (peps.python.org)

References

  1. Python Release Python 3.15.0python.org
  2. PEP 790 – Python 3.15 Release Schedulepeps.python.org
  3. What’s new in Python 3.15docs.python.org
  4. PEP 810 – Explicit lazy importspeps.python.org
  5. PEP 814 – Add frozendict built-in typepeps.python.org
  6. PEP 661 – Sentinel Valuespeps.python.org
  7. PEP 686 – Make UTF-8 mode defaultpeps.python.org
  8. PEP 798 – Unpacking in Comprehensionspeps.python.org
  9. PEP 799 – A dedicated profiling package for organizing Python profiling toolspeps.python.org
  10. PEP 803 – “abi3t”: Stable ABI for Free-Threaded Buildspeps.python.org