Skip to content

__import__ too eager, make it lazy #161721

Closed as not planned
Closed as not planned

Description

@JadenV15

Bug report

We have an inconsistency:

import <module> -> ModuleType | LazyImportType
lazy import <module> -> ModuleType | LazyImportType
__lazy_import__(<module>) -> ModuleType | LazyImportType

importlib.import_module(<module>) -> ModuleType
importlib.__import__(<module>) ->ModuleType
__import__(<module>) -> ModuleType

At its core, the issue seems to be that __lazy_import__ checks lazy filters, but __import__ doesn't.

Consider:

import sys

def my_filter(importing, imported, fromlist):
    return True

sys.set_lazy_imports_filter(my_filter)
sys.set_lazy_imports('all')

import json

print(type(globals()['json']))

Outputs <class 'lazy_import'> as expected.

But switching the import json to json = __import__('json') (or importlib.import_module or importlib.__import__) outputs <class 'module'>.

Not only is that inconsistent with import stmt, it's inconsistent with lazy import. Consider:

import sys

def my_filter(importing, imported, fromlist):
    return False

sys.set_lazy_imports_filter(my_filter)

lazy import json

print(type(globals()['json']))

The output changes depending on True / False in the filter, which is intended. It also works if I switch out lazy import json for json = __lazy_import__('json').

CPython versions tested on:

3.15

Operating systems tested on:

Windows

Activity

  1. picnixz commented on Nov 10, 2026

    @picnixz
    Member

    Unless this was documented differently I believe this is the correct behavior though. __import__ is a low-level primitive you are not meant to call directly and it would make more sense to me that it remains as is.

    cc @DinoV @pablogsal

  2. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    pendingThe issue will be closed if no feedback is provided
    on Nov 11, 2026
  3. picnixz commented on Nov 11, 2026

    @picnixz
    Member

    Rationale why I believe so: in some cases, you might want to have a primitive that ignores any existing filters and bypasses the "all" lazy mode in case you need an eager import, and i believe __import__ should do that. As for __lazy_import__, I believe it should return either a real or true module module since it doesn't know whether it was already imported I guess (and we also removed the "no lazy import" mode I think).

    OTOH, if it's easier to bring the code to parity, we can consider it. But that could break existing projects that relied on the fact that __import__ is unconditinally eager. I haven't read the PEP in its entirety but I'd like to know first if the original specs considered this or not.

  4. JadenV15 commented on Nov 12, 2026

    @JadenV15
    Author

    @picnixz

    1. __import__ bypasses lazy filters; how can I respect lazy filters? There's no __dynamically_import_while_respecting_lazy__().
    2. __import__ bypasses lazy filters but __lazy_import__ doesn't. How can this inconsistency be explained? What if I want __lazy_import__ to bypass lazy filters too?
  5. changed the title [-]__import__ too greedy, make it lazy[/-] [+]__import__ too eager, make it lazy[/+] on Nov 12, 2026
  6. picnixz commented on Nov 12, 2026

    @picnixz
    Member
    1. Don't use a low-level primitive.
    2. That was decided as part of the PEP I believe.

    As I said, if the PEP does not specify the behavior of __import__ it might be tricky to change it. This is why I asked whether there was something about it and why I asked the PEP authors first.

  7. JadenV15 commented on Nov 12, 2026

    @JadenV15
    Author

    Edited to include examples from importlib

  8. picnixz commented on Nov 12, 2026

    @picnixz
    Member

    I looked at the PEP and https://peps.python.org/pep-0810/#unchanged-semantics says:

    Regular import and from ... import ... statements remain eager unless explicitly made potentially lazy by the local or global mechanisms provided.
    Dynamic import APIs remain eager and unchanged: __import__() and `importlib.import_module().

    So this is working as intended.

  9. removed
    type-bugAn unexpected behavior, bug, or error
    on Nov 12, 2026
  10. changed the title [-]__import__ too eager, make it lazy[/-] [+]`__import__` too eager, make it lazy[/+] on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)pendingThe issue will be closed if no feedback is providedtopic-lazy-imports

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions