Skip to content

inspect.getframeinfo forces all lazy modules to be loaded #139669

Open

Description

@SpecLad

Bug report

Bug description:

Create two files as follows:

main.py:

import importlib.util
import inspect
import sys

# https://docs.python.org/3/library/importlib.html#implementing-lazy-imports
def lazy_import(name):
    spec = importlib.util.find_spec(name)
    loader = importlib.util.LazyLoader(spec.loader)
    spec.loader = loader
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    loader.exec_module(module)
    return module
    
lazy_import('m')

f = inspect.currentframe()
inspect.getframeinfo(f)

m.py:

print("I'm loaded!")

Now run:

$ python main.py 
I'm loaded!

This behavior doesn't make much sense, since f isn't even inside m.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Oct 6, 2025
  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Oct 6, 2025
  3. ramicats commented on Oct 7, 2025

    @ramicats

    The inspect module's getframeinfo(frame, context) calls getmodule(frame, file) and that creates a module / filename cache by iterating through sys.modules & accessing their attributes. Since lazy_import(name) adds the lazy module to sys.modules, sys.modules[name] = module - the lazy module gets initialized when accessing the attribute (see "__getattribute__" in LazyModule for more info on accessing attrs).

    Need someone with more expertise in stdlibs to comment on if there's a possible workaround but the mutation checks for the lazy module attributes is the reason the module is being loaded.

  4. ramicats commented on Oct 7, 2025

    @ramicats

    On hindsight, it seems like the inspect module only accesses the __file__ attribute of sys.modules. If it's ok to have an early return on certain immutable attributes that are derived from ModuleSpec metadata in LazyModule (like file in this instance), then we could evade the issue. Looking forward to thoughts from others, I have a working fix if this gets the ok.

  5. xuantengh commented on Oct 8, 2025

    @xuantengh
    Contributor

    Just my two cents: I think it's the expected behavior? The lazy module should be triggered to load at the time it is firstly accessed, wherever this happens, in user code or in first-party libraries.

  6. ramicats commented on Oct 8, 2025

    @ramicats

    Yep, I agree accessing a lazy module's attributes triggering a load is expected. I still think it's not ideal that an introspection tool has a side effect of executing lazy modules. The mutated values tracking only checks for non-metadata attributes i.e. '__dict__', therefore I think a change might be warranted (?) to early return metadata attributes. @picnixz

  7. picnixz commented on Dec 31, 2025

    @picnixz
    Member

    I agree with xuantengh. While it's not ideal as a side-effect, lazy modules are really meant to be lazy until they are needed. Here, we "somehow" need it as a side effect but making special cases isn't enough IMO. inspect is known to create side-effects, either by evaluating signatures, or other stuff like that. With PEP-810 being accepted, I'm not sure that it will be the case anymore, so I would first close the issue now and possibly re-open it for 3.15 and later if this behavior is still inacceptable.

    OTOH, if we were to pre-load some attributes on the lazy module, maybe.. it could work?

    cc @serhiy-storchaka

  8. seberg commented on May 29, 2026

    @seberg
    Contributor

    We just noticed this (indirectly and there the core issue can be argued to not be this). FWIW, I think this is an issue that would be nice to address (although, yeah, PEP-810 may not suffer from the same issue and replace this eventually).

    The problem isn't that there are side-effects and inspect.<something>(lazy_module) loads the module after all.
    But using some inspect API e.g. during import should be reasonable and not break all other loaded modules decision to do lazy imports to speed things up.

    OTOH, if we were to pre-load some attributes on the lazy module, maybe.. it could work?

    Well, there are two possible solutions here, I think, assuming that overriding __file__ on a module is crazy:

    1. Just define __file__ to module.__spec__.origin on the _LazyModule which is probably enough for inspect to get things right.
    2. Have inspect know about importlib.util._LazyModule? E.g. trying module.__spec__.origin rather than __file__ first in the inspect module might be sufficient to not rely on it directly?
  9. serhiy-storchaka commented on May 29, 2026

    @serhiy-storchaka
    Member

    Setting __file__ may also fix other code that checks __file__. cc @brettcannon

  10. xuantengh commented on Jun 1, 2026

    @xuantengh
    Contributor

    We should also set __name__ of _LazyModule to avoid inspect loading the lazy module. May I propose a PR for this?

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

    stdlibStandard Library Python modules in the Lib/ directorytopic-importlibtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions