Repository navigation
Names that have been resolved are not consistently removed from sys.lazy_modules #155695
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Aug 13, 2026 - addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Aug 13, 2026 prithviraj-chaudhuri commented
on Aug 28, 2026 on Aug 28, 2026 · Hidden as outdatedshow commentMore actionsprithviraj-chaudhuri commented
on Sep 9, 2026 on Sep 9, 2026 · Hidden as outdatedshow commentMore actionsI'm not working on a PR for this right now. As @picnixz said though, there's no clear answer on what to do though.
The documentation has been changed since I made this issue and now states:
When a lazily imported module is accessed for the first time, its name is typically removed from this set.
So technically it now matches the documentation but I don't think this is good behaviour that we should have.
psyedgufran-svg commented
on Sep 10, 2026 on Sep 10, 2026 · Hidden as outdatedshow commentMore actionscc @DinoV @pablogsal for what they think we should do here (and whether we should do anything as well)
Reacted by Bartosz SławeckiI see two ways to go here:
- Immediately return cached
sys.modulesentry inlazy import x - Clean up
sys.lazy_modulesin cached paths (regular import or cachedlazy import x+ cachedlazy from x import X)
For (1), plain
lazy import xcurrently creates a proxy and addsxtosys.lazy_modules, even if the module is already cached. Accessing the proxy later calls the ordinary import machinery, whose cache lookup returns the existing module.lazy from x import Xalready has an eager cache fast path, i.e. ifxis cached insys.modulesand that dictionary containsX, it returns that attribute directly instead of creating an attribute proxy.I prefer we check the cache in
lazy import xand return early too, sincelazy from x import Xalready does that.For (2), cleanup currently happens when a module is loaded (not returned from cache).
_find_and_load_unlocked()calls_imp._set_lazy_attributes()after loading, and that function discards the loaded module's name fromsys.lazy_modules.lazy fromregisters the parent module name and the qualified imported name, such asx.Xbefore taking its eager attribute fast path, so consequently:- If resolving
Xloadsx, cleanup removesx, but an ordinary attribute entryx.Xremains. - If
Xis a submodule actually loaded asx.X, its module-loading path removesx.X. - If
xand its attributeXare already available, the eager fast path returnsXwithout removing either entry.
I believe we can fix both (1) and (2).
Reacted by Petr Viktorin and David Ellis- Immediately return cached
Judging by the fact that we already do cache
lazy from x import X, I think it's correct to do the same in the simpler case,lazy import x. We should definitely clean upsys.lazy_modulesin cached paths, so there is something to do regardless. I'll start making a patch, we can iterate. EAFP.Reacted by Brittany ReynosoHi, I'm working with @pablogsal to tie up loose ends around Lazy Imports ahead of the 3.15 final cut.
In the sake of time, I put together a PR to address both parts (1) and (2) of the issue. If you already have a change that you prefer--no hard feelings! That works too.@brittanyrey No worries at all, I hope I helped here. I can help reviewing, ping me anytime. Thanks for taking over and working on this.
Reacted by Brittany Reynoso- added 5 commits that reference this issue
on Sep 26, 2026 - added a commit that references this issue
on Oct 2, 2026 - added a commit that references this issue
on Oct 2, 2026
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Bug report
Bug description:
I'm slightly hesitant to raise this because there's still discussion over what
sys.lazy_modulesshould be. The documentation forsys.lazy_modulescurrently states:In at least two cases I'm aware of names are not being removed. Names may also not be modules, but I'd consider that a documentation issue while I believe the failure to remove names is a bug.
Names of modules that have previously been resolved will be re-added, but not removed when resolved again.
Here I think the issue is adding
xback tosys.lazy_moduleswhen it's already insys.modules.Names that are not modules are not removed:
CPython versions tested on:
3.15, CPython main branch
Operating systems tested on:
No response
Linked PRs