# PEP 810: Explicit lazy imports

**URL:** <https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131>\
**Category:** PEPs\
**Created:** [October 3, 2025, 11:50am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131 "2025-10-03T11:50:19Z")\
**Posts on this page:** 20\
**Page:** 8

<div class="post-metadata">

**Author:** ![Kobzol](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/kobzol/32/12682_2.png) [@Kobzol](https://discuss.python.org/u/Kobzol)\
**Post date:** [October 6, 2025, 8:22pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/144 "2025-10-06T20:22:14Z")

</div>

> [@brettcannon](#):
>
> Have you done an analysis to back that statement up? For instance, I see most imports import modules, so it really depends on what codebases you’re exposed to. As for side-effects, technically every import is a side-effect since it’s an `exec()` call on the source (for the default, pure Python case).

I don’t, it’s hand-waving 🙂 It matches my experience with many Python projects, but YMMV, of course. I would note that importing modules is also usually (again, in my experience) without side effects, you just use a type/function from it later, so I don’t see that being different from importing a function directly.

> [@brettcannon](#):
>
> In that spirit, I don’t think asking us to type 5 more characters when the perf matters is a big deal.

I think that’s fine on its own. I just wondered if the potential community aspect of people spamming PRs to random projects to “optimize” them, or Python developers proactively using lazy import everywhere, was considered. It’s something that we have been thinking about a lot for new opt-in perf-oriented features in Rust, so I thought I’d mention it here, as I didn’t see it being discussed.

> But ignoring all of that, making eager the opt-in is a bit hostile towards beginners where reasoning about lazy imports is harder than lazy imports. In that spirit, I don’t think asking us to type 5 more characters when the perf matters is a big deal.

I think that the reasoning is complicated in both situations. It’s not trivial to benchmark the effect of making a single import in a Python program lazy, it might be difficult to understand the performance characteristics, which could lead to the “premature lazy optimization” behavior I described above.

Features normally have a set of trade-offs. If developers knew that this feature can make their code 5x slower or 5x faster, it’s clear that they would have to think hard about its usage, and not use it willy-nilly everywhere. But if the story is more like “this either has essentially no performance downside or it can make your code faster and take less memory” (which, as far as I understand, is the case), then that might lead to a world where the optimal behavior is to simply use a lazy import everywhere.

---

<div class="post-metadata">

**Author:** ![barry](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/barry/32/42_2.png) [@barry](https://discuss.python.org/u/barry)\
**Post date:** [October 6, 2025, 8:40pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/145 "2025-10-06T20:40:44Z")

</div>

> [@pablogsal](#):
>
> I don’t mind but I think @thomas has a point that this is kind of implied and that if we start to have to write it everywhere (not only on this PEP but other places) it may be a slippery slope. I will let you two to discuss offline 😉

Maybe @thomas and I will still need to duke it out, but here’s my suggestion for addition to the [filter](https://peps.python.org/pep-0810/#lazy-imports-filter) section:

> The filter function is called at the point of execution of the `lazy import` or `lazy from import` statement, not at the point of reification. The filter function may be called concurrently.

There’s still the performance impact of the filter function to address. I’m assuming that if there is no filter function (likely the common case), there’s a fast short-circuit. If so, it begs the question of how to _unset_ the filter function, and I assume that calling `set_lazy_imports_filter(None)` will do that. It might be worth mentioning in the PEP, but it’s definitely worth mentioning in any future documentation.

---

<div class="post-metadata">

**Author:** ![pablogsal](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pablogsal/32/32246_2.png) [@pablogsal](https://discuss.python.org/u/pablogsal)\
**Post date:** [October 6, 2025, 8:43pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/146 "2025-10-06T20:43:09Z")

</div>

> [@barry](#):
>
> There’s still the performance impact of the filter function to address

I added a full new section about this and tagged you on the PR 😉

Short story:

- No filter function by default: quick NULL check and therefore no impact.
- if you install a function the baseline impact is negligible
- If your installed function does stuff then is as expensive as what you do

I also tagged you on a big PR addressing some of your proposed nitpicking 🙂

Check the PEP for more details 🙂

---

<div class="post-metadata">

**Author:** ![barry](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/barry/32/42_2.png) [@barry](https://discuss.python.org/u/barry)\
**Post date:** [October 6, 2025, 8:43pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/147 "2025-10-06T20:43:16Z")

</div>

> [@pablogsal](#):
>
> Yes! Either in `types` or `importlib`. Any preference?

Since you’re gonna move the filter function getter and setter to `importlib` 😉 it makes sense to me for the type to be there too.

---

<div class="post-metadata">

**Author:** ![pablogsal](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pablogsal/32/32246_2.png) [@pablogsal](https://discuss.python.org/u/pablogsal)\
**Post date:** [October 6, 2025, 8:54pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/148 "2025-10-06T20:54:43Z")

</div>

Ok, it’s poll time!

_Poll ([view on site](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/148))_

Blockquote

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [October 6, 2025, 8:54pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/149 "2025-10-06T20:54:56Z")

</div>

> [@pablogsal](#):
>
> Yes! Either in `types` or `importlib`. Any preference?

It’s a “secret” type instantiated internally by the interpreter/runtime - to me, that says `types`. Save `importlib` for things that are part of an API that users may need to use/implement directly.

* * *

Oh, and if you’re going to call it a “lazy object type” and not a “lazily imported module type”, then you’d better think about how it will one day be extended to apply to any object at any time 😉 (or just name it something specific to imports)

---

<div class="post-metadata">

**Author:** ![pablogsal](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pablogsal/32/32246_2.png) [@pablogsal](https://discuss.python.org/u/pablogsal)\
**Post date:** [October 6, 2025, 8:57pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/150 "2025-10-06T20:57:58Z")

</div>

> [@steve.dower](#):
>
> lazily imported module type

Definitely “ lazily imported module type”. Updated the poll

---

<div class="post-metadata">

**Author:** ![yoavdw](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/yoavdw/32/15524_2.png) [@yoavdw](https://discuss.python.org/u/yoavdw)\
**Post date:** [October 6, 2025, 10:51pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/151 "2025-10-06T22:51:03Z")

</div>

> [@pablogsal](#):
>
> security-sensitive tools like `pip` can and should disable laziness right at startup with `sys.set_lazy_imports("disabled")`

Once concern I have, and`pip` doesn’t have this problem, since it’s usually not used as a library, is library authors using `sys.set_lazy_imports(“disabled”)` inside their module and then not re-enabling it. It’s also unclear to me if they can actually re-enable it in all use cases, since there’s not really anywhere to put it, if they want it `disabled` for all calls to their functions.

This will diminish the lazy-import performance gains for the rest of the application (even more so if the user set it to `enabled`).

It seems destructive to me to keep this in it’s current state - I’m worried some library down the chain will do this and it’ll make the feature much less useful to a lot of people, without them even knowing. I tried to come up with a solution, but I couldn’t think of one that works well.

I read the entire thread and hasn’t seen anyone mention this, so please let me know if I’m missing something here and it’s not actually an issue 🙂

---

<div class="post-metadata">

**Author:** ![pablogsal](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pablogsal/32/32246_2.png) [@pablogsal](https://discuss.python.org/u/pablogsal)\
**Post date:** [October 6, 2025, 10:54pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/152 "2025-10-06T22:54:10Z")

</div>

> [@yoavdw](#):
>
> is library authors using `sys.set_lazy_imports(“disabled”)` inside their module

Library authors should not disable lazy imports inside their libraries. Please see the previous discussion regarding the global flag to disable and the PEP updates but short story: it’s an advanced feature for end users (here `pip` is an end user because its exposed as a program on its own) and you need to be aware of the consequences. See also [this section](https://peps.python.org/pep-0810/#allowing-the-filter-to-force-lazy-imports-even-when-globally-disabled) for some related extra context

---

<div class="post-metadata">

**Author:** ![matthewyu0311](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/matthewyu0311/32/20118_2.png) [@matthewyu0311](https://discuss.python.org/u/matthewyu0311)\
**Post date:** [October 6, 2025, 10:59pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/153 "2025-10-06T22:59:16Z")

</div>

`types` has the advantage of having the “lazily imported module type” living together with [types.ModuleType](https://docs.python.org/3/library/types.html#types.ModuleType).

I like the general idea of lazy import, and as many posters noted the purported benefits of lazy import is quite large and people including me will try to use it everywhere. I get the impression thata most modules, except in a few cases, would support being lazily imported out-of-the-box.

Still, users will want find out if a module can be lazily imported. All is good if the library author explicitly states that a module can be lazily imported (or not). If that’s not the case, as with legacy modules, the PEP states

> Test that side-effect timing changes don’t break functionality.

and

> When in doubt, test lazy imports with your specific use cases.

Testing is obviously important but nonetheless certain forms of breakages are things getting _subtly wrong_ timings and thus hard to test, for example reading a config file at a wrong time, initializing an event loop or database connection from a wrong thread. These are all classic heavyweight operations that will certainly benefit from lazy import when someone just wants `--help` from the command line. But what should users and authors do about them? How can library authors make their code compatible with lazy import? Will there be a HOWTO documentation on lazy import patterns?

---

<div class="post-metadata">

**Author:** ![Abdulsm](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/abdulsm/32/31526_2.png) [@Abdulsm](https://discuss.python.org/u/Abdulsm)\
**Post date:** [October 6, 2025, 11:29pm UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/154 "2025-10-06T23:29:28Z")

</div>

> [@matthewyu0311](#):
>
> `types` has the advantage of having the “lazily imported module type” living together with [types.ModuleType](https://docs.python.org/3/library/types.html#types.ModuleType).

Yeah but `importlib` is where the rest of the features are, so I think that’s not an direct winning argument.

> [@matthewyu0311](#):
>
> Still, users will want find out if a module can be lazily imported. All is good if the library author explicitly states that a module can be lazily imported (or not). If that’s not the case, as with legacy modules, the PEP states
> 
> > Test that side-effect timing changes don’t break functionality.
> 
> and
> 
> > When in doubt, test lazy imports with your specific use cases.
> 
> Testing is obviously important but nonetheless certain forms of breakages are things getting _subtly wrong_ timings and thus hard to test, for example reading a config file at a wrong time, initializing an event loop or database connection from a wrong thread. These are all classic heavyweight operations that will certainly benefit from lazy import when someone just wants `--help` from the command line. But what should users and authors do about them? How can library authors make their code compatible with lazy import? Will there be a HOWTO documentation on lazy import patterns?

As I understand the PEP, library authors don’t need to do anything to “support” lazy imports in the default mode. When someone writes `lazy import your_library`, that’s the importing code’s decision and responsibility not yours as the library author. The important part is that your library code doesn’t change at all internally by someone lazy importing it. Whether someone imports your library with `import your_library` or `lazy import your_library`, your module executes exactly the same way and the only difference is _when_ it executes (at import time vs. first use). This timing shift is the importer’s concern to manage, not yours.

The guidance in “How to Teach This” (avoiding import-time side effects, using explicit initialization functions, etc.) is primarily for those who want to use the advanced global mode out of the box. Even then, as someone noted before library maintainers can reasonably decide not to support global mode.

The PEP’s “How to Teach This” section already provides concrete points for supporting the global mode. But I assume this will translate into a better “How to” document about it. Indeed: if we sneakily spy on [this in progress PR by the authors](https://github.com/python/peps/pull/4636/files#diff-ca0112672b06aae6c30c7d4213a58c42f2ad76dd1ec2a17bdc77e988fe75a6cbR914) you can see that they indeed want to do exactly that.

---

<div class="post-metadata">

**Author:** ![dimaqq](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dimaqq/32/372_2.png) [@dimaqq](https://discuss.python.org/u/dimaqq)\
**Post date:** [October 7, 2025, 12:02am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/155 "2025-10-07T00:02:35Z")

</div>

I apologise for too many back-and-forths with a spec supporters who are not the PEP authors.

Mine is only one person’s opinion:

- A proposal to change language syntax must to clear a very high bar
- There has to be a working tentative implementation ✅
- There have to be examples of real-world projects using this implementation ⏳

Prior art is useful, however a curated, reproducible evidence is what’s needed.

Shifting the burden to the readers is a show-stopper for me (one person).

---

<div class="post-metadata">

**Author:** ![dimaqq](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dimaqq/32/372_2.png) [@dimaqq](https://discuss.python.org/u/dimaqq)\
**Post date:** [October 7, 2025, 12:10am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/156 "2025-10-07T00:10:02Z")

</div>

A technical question: what is the proposed C API to load modules lazily and to resolve lazily-loaded modules?

In my (published, no users) extension, I currently have:

> <https://github.com/dimaqq/otlp-proto/blob/main/src/lib.rs#L331-L335>

Which is the equivalent of `import functools` at the start of a module.

What would that look like (API) and work like (semantics) if I wanted a lazy import instead?

---

<div class="post-metadata">

**Author:** ![matthewyu0311](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/matthewyu0311/32/20118_2.png) [@matthewyu0311](https://discuss.python.org/u/matthewyu0311)\
**Post date:** [October 7, 2025, 12:14am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/157 "2025-10-07T00:14:31Z")

</div>

> [@Abdulsm](#):
>
> When someone writes `lazy import your_library`, that’s the importing code’s decision and responsibility not yours as the library author.

Since top-level module code is run when a module is imported, the “`import` convention” should be considered an entry point and thus part of a library’s public API. It is as much a responsibility of the library author to document the sensitivity of their module-level code (which gets run on import) to external state and thus requires additional care on import.

---

<div class="post-metadata">

**Author:** ![yicopa3177](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/yicopa3177/32/31525_2.png) [@yicopa3177](https://discuss.python.org/u/yicopa3177)\
**Post date:** [October 7, 2025, 12:15am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/158 "2025-10-07T00:15:15Z")

</div>

> [@dimaqq](#):
>
> I apologise for too many back-and-forths with a spec supporters who are not the PEP authors.
> 
> Mine is only one person’s opinion:
> 
> - A proposal to change language syntax must to clear a very high bar
> - There has to be a working tentative implementation ✅
> - There have to be examples of real-world projects using this implementation ⏳
> 
> Prior art is useful, however a curated, reproducible evidence is what’s needed.
> 
> Shifting the burden to the readers is a show-stopper for me (one person).

This thread contains direct feedback from maintainers of several projects such as attrs, FastAPI, Scientific Python, stamina, PySide, and other major libraries stating they would immediately benefit from this feature. The PEP documents that several major companies Meta, Google, HRT, and Bloomberg already use similar implementations in production at scale with measured performance gains. Some users have shared resources in articles, bug tracker items and other links.

Python doesn’t require real-world adoption before accepting syntax changes. For example pattern matching was accepted without requiring projects to prove adoption. The evidence here (production use + direct enthusiasm from library maintainers in this discussion) exceeds typical standards.

The “burden” you mention isn’t being shifted. I think your requests here are unfair

---

<div class="post-metadata">

**Author:** ![Abdulsm](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/abdulsm/32/31526_2.png) [@Abdulsm](https://discuss.python.org/u/Abdulsm)\
**Post date:** [October 7, 2025, 12:21am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/159 "2025-10-07T00:21:15Z")

</div>

> [@matthewyu0311](#):
>
> Since top-level module code is run when a module is imported, the “`import` convention” should be considered an entry point and thus part of a library’s public API. It is as much a responsibility of the library author to document the sensitivity of their module-level code (which gets run on import) to external state and thus requires additional care on import.

I think you’re misunderstanding how this works. As a library author, you don’t write your code any differently. Your module executes identically whether someone uses `import your_library` or `lazy import your_library`.

The `lazy` keyword affects **the importer** , not the library being imported. When someone chooses to lazy import your library, they’re accepting the timing change. That’s their responsibility, not yours.

Unless I am missing something you don’t need to document anything special or make your code “compatible with lazy imports.” (unless you want it to work under the global flag). With the normal mode your library’s behavior is unchanged.

---

<div class="post-metadata">

**Author:** ![kapinga](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/kapinga/32/24087_2.png) [@kapinga](https://discuss.python.org/u/kapinga)\
**Post date:** [October 7, 2025, 12:34am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/160 "2025-10-07T00:34:39Z")

</div>

Put another way: library authors already have no control over when their module is imported. Users might have code like this today:

```python
def func_a():
    import your_module
    your_module.some_func()

def main():
    …. # lots of code here
    func_a()

main()

```

With lazy imports, they might change this to be:

```python
lazy import your_module

def func_a():
    your_module.some_func()

```

with no practical difference at runtime.

Thus: if your module has special requirements about when it can be imported, it’s already incumbent on you to clearly document these to consuming code. The only thing that would change is to include consideration of lazy imports into that documentation.

---

<div class="post-metadata">

**Author:** ![blhsing](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/blhsing/32/25812_2.png) [@blhsing](https://discuss.python.org/u/blhsing)\
**Post date:** [October 7, 2025, 1:56am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/161 "2025-10-07T01:56:53Z")

</div>

> [@dmoisset](#):
>
> 1. The `try`restriction seems to prevent using this feature in the very common pattern where an “optional” module is attempted to be loaded, and a fallback mechanism (either providing an alternative source or dummy replacement) is provided in the except clause.

> [@sirosen](#):
>
> ```python
> try:
> from foo import bar
> except ImportError:
> from baz import bar
> 
> ```

Switching to a fallback/alternative upon a failed import is a rather common pattern and it’d be somewhat of a bummer if one has to revert to using eager import for handling `ImportError`.

Maybe there can be an extended syntax for registering a block of exception handler that’s executed in the same frame upon `ImportError` when the name is reified:

```python
try lazy from fastfoo import bar except: # implicitly handles ImportError only
    from oldfoo import bar
    # or: bar = more_compatible_bar
    # or: raise RuntimeError("Friendlier error message.")

if action == "print":
    print(bar())
elif action == "errorcode":
    sys.exit(bar())
else:
    print("Usage: foo <print | errorcode>")

```

so that there’ll be no need to handle `ImportError` in multiple places downstream where `bar` may be first used.

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [October 7, 2025, 2:20am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/162 "2025-10-07T02:20:25Z")

</div>

When needed, this can be accomplished with a very simple wrapper module…

```python
main.py:
---
lazy from whatever_bar import bar

whatever_bar.py:
---
try:
    from fastfoo import bar
except ImportError:
    from oldfoo import bar

```

It’d be a bunch of boilerplate to maintain a bunch of those wrappers, but it’s a lot simpler than adding syntax.

---

<div class="post-metadata">

**Author:** ![hprodh](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/hprodh/32/22529_2.png) [@hprodh](https://discuss.python.org/u/hprodh)\
**Post date:** [October 7, 2025, 4:23am UTC](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131/163 "2025-10-07T04:23:55Z")

</div>

> [@tjstum](#):
>
> Reification imports the module in the same way as it would have been if it had been imported eagerly, barring intervening changes to the import system (e.g. to `sys.path`, `sys.meta_path`, `sys.path_hooks` or ` __import__ `).

Is the following a correct rephrasing ?  
“”"  
Reification imports the module in the same way as it would be done eagerly at reification time, employing the current state of the import system (i.e. of `sys.path`, `sys.meta_path`, `sys.path_hooks`, ` __import__ `, `importlib`, `sys.modules` and PYTHONPATH).  
“”"

[Previous page](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131.md?page=7)

[Next page](https://discuss.python.org/t/pep-810-explicit-lazy-imports/104131.md?page=9)
