Repository navigation
Description
Bug report
(Edited by @johnslavik)
To reproduce:
import importlib.metadata
import importlib.metadata as x
lazy import importlib.metadata as lazy_x
print("type(x): ", type(x).__name__) # reifies to importlib.metadata
print("type(lazy_x):", type(lazy_x).__name__) # reifies to importlib.metadata.metadata
x.distributions() # OK
lazy_x.distributions() # AttributeError: 'function' object has no attribute 'distributions'x is the importlib.metadata module, as expected. lazy_x is instead reified to importlib.metadata.metadata, the function.
The bug is in cached name resolution.
For lazy import a.b as c, the issue reproduces when:
a.bis already insys.modules.a.bhas an attribute namedb.cis reified.
Possible root cause
The problem may be in _PyEval_LazyImportFrom: [Python/ceval.c:3305-3361](https://github.com/python/cpython/blob/cf312cfa64dcaa1700531ec8bc76d56ddd65fb15/Python/ceval.c#L3305-L3361) (3.15 at cf312cfa64dcaa1700531ec8bc76d56ddd65fb15, v3.15.0rc2-22-gcf312cf).
The sys.modules fast path at lines 3313-3331 runs before the base-module computation at 3333-3360 and looks up name directly in d->lz_from.
In the IMPORT_FROM chain generated for import a.b.c as x, however, d->lz_from does not appear to be the module the attribute should be taken from: on the first step it is the full dotted name, and on later steps it is one component short of the base.
CPython versions tested on:
3.15
Operating systems tested on:
Linux
Linked PRs
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsTodo
Activity
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
johnslavik commentedon Sep 16, 2026
Thanks for reporting the issue, I've reproduced it.
You've opened a PR in your fork repo, not in CPython.
grgalex commentedon Sep 16, 2026
@johnslavik Thanks for reproducing!
Ahhh the PR on the fork references the issue so it appears here. Was testing some stuff!
I'll submit the associated PR once it's ready (soon!) :)
johnslavik commentedon Sep 16, 2026
@grgalex In the test please create a package structure to be imported, don't rely on
importlib.metadatabecause that API can change. We should test the pattern, not something that happens to accidentally be an instance of it today.pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
pythongh-157614: Make the lazy import subprocess test helper reusable
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
11 remaining items
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
pythongh-157614: Make the lazy import subprocess test helper reusable
pythongh-157614: Fix lazy import a.b as c binding a.b.b instead of th…
grgalex commentedon Sep 16, 2026
@johnslavik I've opened the PR.
Next time I'll make sure not to link to the main issue during experimentation in the private fork to avoid polluting the issue with references!
StanFromIreland commentedon Sep 16, 2026
Marking as a release-blocker to get Hugo's eyes on this. This seems pretty bad, and seems like a realistic scenario to hit in practice.
[-]lazy import a.b as c incorrectly binds a.b.b[/-][+]`lazy import a.b as c` incorrectly binds to `a.b.b`[/+]grgalex commentedon Sep 18, 2026
Another bug found while investigating the present issue: #157757
hugovk commentedon Sep 28, 2026
Fixed by #158092, removing release-blocker label. Keeping this issue open for now to decide if we want the test from #157626.