{"slug": "python-3-15-lazy-imports-frozendict-and-a-faster-jit", "title": "Python 3.15: Lazy Imports, frozendict, and a Faster JIT", "summary": "Python 3.15 shipped on October 9 with explicit lazy imports, a built-in frozendict type, and JIT improvements, per the release's PEP 810 and PEP 814 documentation. Meta's codebase saw a 70% reduction in initialization time after adopting lazy imports, which defer module loading until first use. The JIT compiler now shows 7–8% geometric mean improvement on x86-64 Linux and 11–12% on AArch64 macOS, up from roughly 2% in 3.13 and 4–5% in 3.14.", "body_md": "Python 3.15 shipped on October 9. The headline feature is [explicit lazy imports](https://peps.python.org/pep-0810/) — a syntax change that defers module loading until first use. Meta’s codebase saw a 70% reduction in initialization time after adopting the pattern. The release also ships `frozendict` as a built-in type, a proper sentinel, unpacking in comprehensions, and a JIT compiler that is finally showing numbers worth quoting. Here is what matters and what to watch.\n\n## Lazy Imports: The Startup Fix Python Needed\n\nFor years, heavy Python apps had a startup problem. A web server importing Django, SQLAlchemy, and a handful of ML libraries could spend 400–800ms doing nothing but running import statements before accepting a single request. The standard fix was manual workaround: move imports inside functions, use `importlib` tricks, or fork CPython like Meta did. Python 3.15 makes this a first-class feature.\n\nThe new `lazy` soft keyword defers module loading until the imported name is first accessed:\n\n``` python\nlazy import json\nlazy from pathlib import Path\n\n# At this point, nothing is loaded — proxy objects only\n# The real import fires on first use:\ndata = json.loads('{\"key\": \"value\"}')\n```\n\nFor projects that need to stay compatible with older Python versions, there is a backwards-compatible approach using the `__lazy_modules__` list. On Python 3.15+, those imports become lazy. On older versions, the list is ignored and imports proceed normally.\n\n``` python\n__lazy_modules__ = ['numpy', 'pandas', 'heavy_analytics_lib']\nimport numpy\nimport pandas\n```\n\nThe practical wins are real. CLI tools are the clearest example — when a user runs `--help`, there is no reason to import a plotting library or a database driver. Meta’s 70% initialization reduction was not a lab benchmark; it came from converting production libraries with deep dependency graphs.\n\nTwo risks worth naming. First: late error detection. An `ImportError` that used to surface at startup will now surface when you first access the lazy import, potentially during request handling or a background job. Second: thread safety. Startup was previously single-threaded; now any thread that first touches a lazy import triggers the load. Neither is a dealbreaker, but both require awareness when adopting this pattern in concurrent systems.\n\n## frozendict: A Built-in That Took 20 Years\n\nPython developers have needed an immutable, hashable dictionary for a long time. The standard library offered `types.MappingProxyType` as a partial answer, but it was a view over a mutable dict — not genuinely hashable, not usable as a dict key. Third-party packages filled the gap. Python 3.15 ships `frozendict` as a proper built-in via [PEP 814](https://peps.python.org/pep-0814/).\n\n``` python\nimport functools\n\nconfig = frozendict({\"model\": \"gpt-4o\", \"temperature\": 0.7})\n\n# Use as a cache key\n@functools.lru_cache\ndef run_query(cfg: frozendict) -> str:\n    ...\n\n# Use as a set member or dict key\nseen_configs = {frozendict(user=\"alice\"), frozendict(user=\"bob\")}\nlookup = {frozendict(scope=\"read\"): handler_fn}\n```\n\nA few things to know before adopting it. `frozendict` is not a `dict` subclass — `isinstance(fd, dict)` returns `False`. That is intentional: it avoids inheriting mutation methods that would need to raise errors. The immutability is also shallow: a nested list inside a `frozendict` is still mutable, and a `frozendict` containing a list cannot be hashed. These are the same constraints that apply to `frozenset`, so the behavior is at least consistent.\n\n## The JIT Keeps Compounding\n\nPython’s experimental JIT has been technically available since 3.13. It has not been worth enabling until now. Python 3.15 shows 7–8% geometric mean improvement on x86-64 Linux and 11–12% on AArch64 macOS, with upgrades to LLVM 21, a new tracing frontend, basic register allocation, and lower memory usage for generated machine code.\n\nThe trajectory matters more than any single number: roughly 2% in 3.13, 4–5% in 3.14, 7–8% in 3.15. The JIT is still experimental and opt-in — it will not activate automatically. It is also not PyPy. But 8% on a distributed workload has real infrastructure cost implications, and the trend line is clearly heading somewhere.\n\n## Smaller Wins Worth Knowing\n\nPython 3.15 also ships `sentinel` as a built-in. The old `_MISSING = object()` pattern works fine but produces ugly reprs and does not pickle cleanly. `sentinel(\"MISSING\")` gives you a named, picklable, identity-preserving sentinel that works properly with type annotations.\n\n[PEP 798](https://peps.python.org/pep-0798/) adds unpacking to comprehensions:\n\n```\n# Before Python 3.15\nflat = [x for sublist in lists for x in sublist]\n\n# Python 3.15\nflat = [*sublist for sublist in lists]\n\n# Merge dicts in one comprehension\nmerged = {**d for d in dict_list}\n```\n\n## What Actually Breaks\n\nUTF-8 is now the default encoding on all platforms. Code that calls `open()` without an explicit `encoding=` argument and relies on locale defaults — especially on Windows — may produce different output. The fix is to pass `encoding=\"utf-8\"` explicitly.\n\nSeveral long-deprecated APIs are now removed: `datetime.utcnow()` (use `datetime.now(datetime.UTC)`), `importlib.resources.read_text()`, and the internal `sre_compile`, `sre_constants`, `sre_parse` modules. The regex internals are the most likely surprise — some packages accessed them directly. Check your dependencies before upgrading. The [official What’s New page](https://docs.python.org/3.15/whatsnew/3.15.html) has the full list.\n\n## Should You Upgrade?\n\nFor greenfield projects: yes. The new built-ins are cleaner than their alternatives, and lazy imports are worth adopting for anything with non-trivial startup cost. For existing projects: check your dependencies first. The UTF-8 default and removed APIs are the likeliest sources of breakage, and most projects will need small fixes rather than rewrites.\n\nPython 3.15 is not a headline release — there is no walrus operator moment, no `match` statement. What it is: a release that fixes chronic annoyances that Python developers have been patching around for years. That is often more valuable than a flashy syntax addition. The [official download is available now](https://www.python.org/downloads/release/python-3150/).", "url": "https://wpnews.pro/news/python-3-15-lazy-imports-frozendict-and-a-faster-jit", "canonical_source": "https://byteiota.com/python-3-15-lazy-imports-frozendict-jit/", "published_at": "2026-10-10 05:08:56+00:00", "updated_at": "2026-10-10 05:28:59.414387+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence"], "entities": ["Python 3.15", "Meta", "CPython", "PEP 810", "PEP 814", "frozendict", "LLVM 21"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/python-3-15-lazy-imports-frozendict-and-a-faster-jit", "markdown": "https://wpnews.pro/news/python-3-15-lazy-imports-frozendict-and-a-faster-jit.md", "text": "https://wpnews.pro/news/python-3-15-lazy-imports-frozendict-and-a-faster-jit.txt", "jsonld": "https://wpnews.pro/news/python-3-15-lazy-imports-frozendict-and-a-faster-jit.jsonld"}}