---
topic: tech
author: Crashtech Editorial
published: Oct 20, 2026 · read: 4 min
---

Python 3.15 Makes Lazy Imports Explicit and UTF-8 the Default

The new stable release adds opt-in lazy imports and changes the default text encoding, creating two different migration checks for Python teams.

– –

“Lazy imports” sounds like a switch that makes every Python application start faster. It is not. Python 3.15 gives developers a way to defer selected imports deliberately, while a separate encoding change affects defaults that many programs inherited from their operating system.

A branching module graph flows toward a multilingual text panel, representing deferred imports and UTF-8 text handling.
Conceptual illustration of the engineering issue discussed in this article.

Lazy means requested, not automatic

The new lazy import form marks an import for deferred loading. The module is imported when an attribute from it is first needed, rather than at the point where the statement appears. This can reduce work on startup paths that never use an optional dependency, but it can also move import errors or module side effects later into program execution. PEP 810 describes the feature as explicit and local; it does not recursively make every dependency lazy. Star imports and future imports are among the restricted cases. [3]

That changes where a failure appears. A missing dependency that used to stop a process during initialization could now fail when a rarely used branch executes. A module that registers plugins or configures logging during import may also behave differently if its import moves past an initialization boundary. The release notes describe a __lazy_modules__ compatibility mechanism for modules that need to interoperate with existing import patterns. [2]

The sensible question is not “does Python 3.15 have lazy imports?” but “which import is expensive, optional and safe to defer in this program?” Profile first. Then change a narrow import and test both the path that uses it and the path that never does. The startup effect depends on your import graph, cache state, operating system and application work.

UTF-8 default changes a different contract

PEP 686 makes UTF-8 mode the default in Python 3.15. The practical impact is most visible where code opens text files without specifying an encoding and previously relied on a machine’s locale. A file written in another legacy encoding may now raise a decoding error, or behavior may change in a pipeline that silently accepted bytes under a platform-specific assumption. [4]

This is not a reason to force every file through UTF-8. It is a reason to make the format explicit. If a partner feed is Windows-1252, declare that. If an internal format is UTF-8, declare that too. Explicit encodings make the program’s expectations portable and make failures easier to diagnose.

Python’s 3.15 notes also describe using encoding warnings in earlier versions to find code that depends on the locale default. For a migration, that offers a useful preparation path: run with warnings enabled, inspect each implicit text-file open, and add a test using the actual encodings found in production inputs. [2]

A measured upgrade path

Start by running the existing test suite on Python 3.15 without enabling lazy imports. That separates runtime compatibility from code changes. Review dependencies and native extensions, then exercise file import/export paths with representative data. For applications with multiple deployment environments, include Windows and container builds rather than assuming local behavior predicts production.

If startup is a problem, collect a baseline with the same cold-start conditions that matter to users. Identify modules imported only by optional routes or commands, convert one at a time, and repeat the measurement. Include first-use latency and failure behavior in the evaluation; moving work from startup to a later request may improve one metric while worsening another.

Finally, define rollback criteria. A deployment can compare startup time, first-request latency, import errors and text-processing failures. If a lazy import shifts a critical setup action or a file boundary changes, the code should fail visibly and locally rather than corrupting output.

Treat the release as two controlled changes

Python 3.15 brings a stable runtime and useful language updates. The safe adoption story is straightforward: verify compatibility on the new interpreter, make text encodings explicit where the format matters, and opt into lazy imports only when measurement supports the change. That turns a broad release announcement into a small set of testable decisions instead of a blanket performance promise.

Advertisement

Frequently asked questions

Does Python 3.15 make every import lazy?

No. Lazy imports are explicit and opt-in under the new syntax. The feature is module-scoped and has limits, including star imports and future imports; existing imports do not silently become lazy across an application.

What should I test before moving to Python 3.15?

Run the suite on the new interpreter, check import-time side effects and deferred failures if using lazy imports, and test files that rely on platform-default encodings. Python 3.15 makes UTF-8 the default, which can expose assumptions that previously followed a locale-specific encoding.

Sources & further reading

/* Comments */