GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — `lazy import a.b as c` resolves `b` as an attribute of `a` instead of importing the module `a.b` · Issue #157757 · python/cpython

lazy import a.b as c resolves b as an attribute of a instead of importing the module a.b #157757

New issue
Copy link
New issue
Copy link
Closed
Closed
lazy import a.b as c resolves b as an attribute of a instead of importing the module a.b#157757
Copy link
Labels
3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)release-blockertopic-lazy-importstype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@grgalex
grgalex
opened on Sep 18, 2026
Issue body actions

Bug report

Bug description:

lazy import a.b as c never imports the module a.b by name. On first use it imports a and reads the attribute b off it, as lazy from a import b would, so c becomes whatever that attribute lookup finds. This manifests in two ways.

Case A: a.b is not a module. The eager statement raises; the lazy one binds the attribute.

lazy import math.pi as lazy_x
print(lazy_x)  # 3.141592653589793

import math.pi as x  # ModuleNotFoundError: No module named 'math.pi'; 'math' is not a package

The bare lazy import math.pi was fixed in #155194; the as form was not.

Case B: a.b is a module, but a has an attribute b that shadows it and a.b has not been imported yet. The eager statement imports the submodule, which rebinds a.b to the module; the lazy one binds the attribute and never imports the submodule. json does not import json.tool, so the assignment below stands in for an attribute a package's __init__.py would define:

import json
json.tool = "attribute"

lazy import json.tool as lazy_c
print(type(lazy_c).__name__)  # str

import json.tool as c
print(type(c).__name__)  # module

Case B is related to #151208, which reports the same shadowing for import a.foo under -X lazy_imports=all followed by an attribute access a.foo, resolved in Objects/moduleobject.c. That script now passes on main; this statement still fails, because it is resolved on a different path.

Possible root cause

import a.b as c compiles to IMPORT_NAME a.b followed by IMPORT_FROM b. Lazily, IMPORT_NAME leaves a placeholder holding a.b, and _PyEval_LazyImportFrom (Python/ceval.c:3329-3384) replaces it with one holding lz_from = "a", lz_attr = "b". That is the same placeholder lazy from a import b produces.

Reification in _PyImport_LoadLazyImportTstate (Python/import.c:3902-4093) therefore runs __import__("a", fromlist=("b",)) followed by getattr(a, "b") for both statements. Nothing records that the statement was an import, so the module a.b is never imported by its own name: the "is not a package" check never runs, and an existing attribute b is never overwritten by the submodule.

This is not #157614, which is about the sys.modules fast path in _PyEval_LazyImportFrom consulting the wrong module. The present issue reproduces with the fix in #157626 applied.

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Linked PRs

  • gh-157757: Fix to make lazy import a.b as c import the module a.b #158092
  • [3.15] gh-157757: Fix to make lazy import a.b as c import the module a.b (GH-158092) #158257

Activity

  1. grgalex
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Sep 18, 2026
  2. StanFromIreland
    added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    release-blocker
    topic-lazy-imports
    on Sep 18, 2026
  3. github-project-automation
    added this to Release and Deferred blockers 🚫on Sep 18, 2026
  4. github-project-automation
    moved this to Todo in Release and Deferred blockers 🚫on Sep 18, 2026
  5. johnslavik commented on Sep 18, 2026

    @johnslavik
    johnslavik
    on Sep 18, 2026
    Member
    More actions

    @brittanyrey

    Reacted by Brittany Reynoso
  6. brittanyrey
    added a commit that references this issue on Sep 18, 2026

    Import the module a lazy `import a.b as c` names

    This issue will close once commit ad1242d is merged into the 'master' branch.
    ad1242d
  7. hugovk
    added
    3.15bugs and security fixesbugs and security fixes
    3.16new features, bugs and security fixesnew features, bugs and security fixes
    on Sep 23, 2026
  8. encukou commented on Sep 24, 2026

    @encukou
    encukou
    on Sep 24, 2026
    Member
    More actions

    @brittanyrey, do you need any help?
    The 3.15.0 release is next week.

    Reacted by Bartosz Sławecki
    Reacted by Brittany Reynoso and Hugo van Kemenade
  9. brittanyrey commented on Sep 24, 2026

    @brittanyrey
    brittanyrey
    on Sep 24, 2026
    Contributor
    More actions

    Hey, @encukou I would really appreciate that!

    I had started working on this one a little bit last week but I wasn't feeling great about the fix I had. I'll put it up as an RFC in case that helps at all. Please take a look and let me know what you think #158092

    (If you don't mind, I'm going to cc you on a few more open lazy imports PRs)

    Reacted by Hugo van Kemenade
  10. johnslavik commented on Sep 24, 2026

    @johnslavik
    johnslavik
    on Sep 24, 2026
    Member
    More actions

    I'll help too! Will review until the end of the week.

    Reacted by Hugo van Kemenade and Brittany Reynoso
  11. brittanyrey commented on Sep 24, 2026

    @brittanyrey
    brittanyrey
    on Sep 24, 2026
    Contributor
    More actions

    Thanks @encukou & @johnslavik. I iterated a bit more on the fix and I think it actually might be good for review & to hopefully land 🤞.

    Reacted by Bartosz Sławecki
  12. pablogsal
    added 3 commits that reference this issue on Sep 26, 2026

    pythongh-157757: Preserve empty fromlists for custom import hooks

    48244f1

    gh-157757: Fix to make `lazy import a.b as c` import the module `a.b` (…

    1e8ff18

    [3.15] gh-157757: Fix to make `lazy import a.b as c` import the modul…

    1a2d24e
  13. hugovk
    closed this as completedon Sep 26, 2026
  14. Kronuz
    added 7 commits that reference this issue on Sep 28, 2026

    Parity check to 3.15 tip 5985fcb: pull pythongh-157757 into lazy imports

    1b46692

    Parity check to 3.15 tip 021f634 (release day): lazy core refactored

    b60a5ad

    [3.15] pythongh-157757: Fix to make `lazy import a.b as c` import the…

    0bf1009

    Record the pythongh-157757 + pythonGH-158282-behaviors backport (clea…

    418fded

    Guard chained lazy-import resolver against non-tuple lz_attr

    2ea30ab

    [3.15] pythongh-157757: Fix to make `lazy import a.b as c` import the…

    2279ffb

    Guard chained lazy-import resolver against non-tuple lz_attr

    b68a11b
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

    3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)release-blockertopic-lazy-importstype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Release and Deferred blockers 🚫
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.