python / python/cpython

`lazy import a.b as c` incorrectly binds to `a.b.b`

Offen
#157,614 6 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

3.15 3.16 interpreter-core release-blocker topic-lazy-imports type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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:

  1. a.b is already in sys.modules.
  2. a.b has an attribute named b.
  3. c is 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
  • gh-157626

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit der Prüfung des verknüpften PR gh-157626 und untersuche anschließend _PyEval_LazyImportFrom in Python/ceval.c etwa in den Zeilen 3305–3361. Konzentriere dich dabei auf den sys.modules-Fast-Path und die Auflösung zwischengespeicherter Namen. Reproduziere das Verhalten mit dem importlib.metadata-Beispiel; fertig ist die Änderung, wenn lazy import a.b as c c an a.b statt an a.b.b bindet und die Regression durch die entsprechenden Tests abgedeckt ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.