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 — gh-158140: Resolve lazily imported sibling submodules independently by pablogsal · Pull Request #158521 · python/cpython

Conversation

@pablogsal

@pablogsal pablogsal commented Sep 30, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Fixes #158140. With lazy import pkg.a followed by lazy import pkg.b, accessing pkg.a currently imports pkg.b first. Resolve ordinary dotted imports through the existing pending-child lookup, without publishing placeholders in package dictionaries. Custom namespace builtins and aliased parents retain their existing import behavior.

The lazy-import, import, importlib, module, sys and C API suites pass in debug and free-threaded builds. Regression tests cover independent siblings, star imports, declaration cleanup, deleted attributes, import hooks and failed-import retries.

  • Issue: Accessing one lazily imported submodule (lazy import pkg.a) also imports a later imported pkg.b #158140

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot mentioned this pull request Sep 30, 2026
Accessing one lazily imported submodule (lazy import pkg.a) also imports a later imported pkg.b #158140
Closed
@hugovk hugovk added the release-blocker label Sep 30, 2026
@github-project-automation github-project-automation Bot added this to Release and Deferred blockers 🚫 Sep 30, 2026
@github-project-automation github-project-automation Bot moved this to Todo in Release and Deferred blockers 🚫 Sep 30, 2026
@pablogsal
pablogsal force-pushed the fix-158140-independent-submodules branch from 662dfea to 56babbc Compare October 1, 2026 18:05
@pablogsal

pablogsal commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

Sorry fucked up the squash give me sec

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal
pythongh-158140: Resolve lazy siblings through the pending-child regi…
4e83bfa
…stry
@pablogsal
pablogsal force-pushed the fix-158140-independent-submodules branch from 56babbc to 4e83bfa Compare October 1, 2026 19:23
@Yhg1s

Yhg1s commented Oct 1, 2026

Copy link
Copy Markdown
Member

Is this ready now @pablogsal?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s
Yhg1s marked this pull request as ready for review October 1, 2026 22:00
@Yhg1s
Yhg1s requested review from DinoV, FFY00, Yhg1s, brettcannon, ericsnowcurrently, kumaraditya303, ncoghlan and warsaw as code owners October 1, 2026 22:00
@bedevere-app bedevere-app Bot added the awaiting core review label Oct 1, 2026
@Yhg1s

Yhg1s commented Oct 2, 2026

Copy link
Copy Markdown
Member

Here's a somewhat surprising change in behaviour: given these two modules:

A.py:

lazy import xml.missing # CORRECT ONE
import B

xml.missing

B.py:

lazy import xml.missing # WRONG ONE

Before this PR the use of xml.missing in A.py will print a traceback showing the lazy import in A.py as the cause:

% base/python A.py
Traceback (most recent call last):
  File "A.py", line 1, in <module>
    lazy import xml.missing # CORRECT ONE
ImportError: lazy import of 'xml.missing' raised an exception during resolution

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "A.py", line 4, in <module>
    xml.missing
    ^^^
ModuleNotFoundError: No module named 'xml.missing'

With this PR, it reports the lazy import in B.py:

% pr/python A.py
Traceback (most recent call last):
  File "B.py", line 1, in <module>
    lazy import xml.missing # WRONG ONE
ImportError: lazy import of 'xml.missing' raised an exception during resolution

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "A.py", line 4, in <module>
    xml.missing
ModuleNotFoundError: No module named 'xml.missing'

Swapping the order of the lazy imports used to not have an effect on the traceback, but now it does: the last lazy import wins. I'm not sure if that's fixable, but I think if we need a single location the first lazy import would be a better winner.

johnslavik reacted with eyes emoji
All reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Oct 2, 2026

Copy link
Copy Markdown
Member

Swapping the order of the lazy imports used to not have an effect on the traceback, but now it does: the last lazy import wins. I'm not sure if that's fixable, but I think if we need a single location the first lazy import would be a better winner.

Okay I think I see why we can't do that, either. I think this is fixable later (perhaps by merging lazy objects, storing all the locations and selecting an appropriate one when printing the traceback). Still, it's a little annoying that this used to work as users would expect.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Oct 2, 2026

Copy link
Copy Markdown
Member

I think there's a similar issue with modules defining __import__, although I don't have a simple reproducer: if you have two different modules lazily importing the same pkg.module, with their own __import__ methods shadowing the builtin __import__, module A may end up calling module B's __import__ when it does its reification. I can't see how to avoid that one without giving A and B its own sys.modules entirely.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Yhg1s
Yhg1s reviewed Oct 2, 2026
View reviewed changes
Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Yhg1s
Yhg1s reviewed Oct 2, 2026
View reviewed changes
Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Yhg1s
Yhg1s approved these changes Oct 2, 2026
View reviewed changes

@Yhg1s Yhg1s left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All things considered, LGTM. I think the semantic changes are acceptable for 3.15 and we can see if we can improve the error reporting later.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Oct 2, 2026
@encukou encukou mentioned this pull request Oct 2, 2026
Nitpicks for removing names from sys.lazy_modules brittanyrey/cpython#1
Open
@hugovk hugovk added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Oct 2, 2026
@bedevere-bot

bedevere-bot commented Oct 2, 2026

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @hugovk for commit 4e83bfa 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F158521%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Oct 2, 2026
encukou
encukou reviewed Oct 2, 2026
View reviewed changes
Comment thread Lib/test/test_lazy_import/__init__.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@encukou encukou mentioned this pull request Oct 2, 2026
gh-155695: Remove resolved names from sys.lazy_modules more consistently #157714
Merged
@pablogsal

pablogsal commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

I think we can fix the A/B case by keeping the declarations keyed by the importing module’s __name__. When accessing the child, we use the current frame’s globals to pick the right one. Custom-builtins imports can stay out of that registry since they already resolve the full path through their own hook.

I tried this locally. It’s about 70 lines of C. There’s still ambiguity if two namespaces share the same name, or the same filename for anonymous exec, but it fixes this case without keeping globals alive.

What do you think, @Yhg1s?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Yhg1s
Yhg1s reviewed Oct 2, 2026
View reviewed changes
Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s

Yhg1s commented Oct 2, 2026

Copy link
Copy Markdown
Member

I think we can fix the A/B case by keeping the declarations keyed by the importing module’s __name__. When accessing the child, we use the current frame’s globals to pick the right one. Custom-builtins imports can stay out of that registry since they already resolve the full path through their own hook.

I tried this locally. It’s about 70 lines of C. There’s still ambiguity if two namespaces share the same name, or the same filename for anonymous exec, but it fixes this case without keeping globals alive.

What do you think, @Yhg1s?

Yes, I was thinking something similar, but I don't think we should try to fix this for 3.15.0. We can pre-emptively file a bug and fix it later.

pablogsal reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal pablogsal mentioned this pull request Oct 2, 2026
Lazy import traceback points to another module's declaration #158597
Open
encukou added 2 commits October 2, 2026 18:22
@encukou
Merge in the main branch
e612bf3
@encukou
Use lazy_import_path, not _name, when discarding from sys.lazy_modules
30be4e1
Only the root is now resolved.
@encukou

encukou commented Oct 2, 2026

Copy link
Copy Markdown
Member

I merged in the main branch with #157714.

hugovk reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s @encukou
Apply batched suggestions from code review
541db05
Co-authored-by: T. Wouters <[email protected]>
Co-authored-by: Petr Viktorin <[email protected]>
Yhg1s
Yhg1s approved these changes Oct 2, 2026
View reviewed changes
Comment thread Lib/test/test_lazy_import/__init__.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/lazyimportobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Yhg1s Yhg1s added the needs backport to 3.15 bugs and security fixes label Oct 2, 2026
@Yhg1s
Yhg1s enabled auto-merge (squash) October 2, 2026 16:36
@Yhg1s
Yhg1s disabled auto-merge October 2, 2026 17:17
@Yhg1s
Merge branch 'main' into fix-158140-independent-submodules
3838b0c
@Yhg1s
Yhg1s enabled auto-merge (squash) October 2, 2026 17:18
@Yhg1s
Yhg1s disabled auto-merge October 2, 2026 17:19
@Yhg1s
Yhg1s merged commit 00a1c3a into python:main Oct 2, 2026
7 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@miss-islington-app

miss-islington-app Bot commented Oct 2, 2026

Copy link
Copy Markdown

Thanks @pablogsal for the PR, and @Yhg1s for merging it 🌮🎉.. I'm working now to backport this PR to: 3.15.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label Oct 2, 2026
@bedevere-app

bedevere-app Bot commented Oct 2, 2026

Copy link
Copy Markdown

GH-158613 is a backport of this pull request to the 3.15 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 bugs and security fixes label Oct 2, 2026
hugovk added a commit that referenced this pull request Oct 2, 2026
@miss-islington @pablogsal
@encukou @Yhg1s @hugovk
[3.15] gh-158140: Resolve lazily imported sibling submodules independ…
03bb26f
…ently (GH-158521) (#158613)

Co-authored-by: Pablo Galindo Salgado <[email protected]>
Co-authored-by: Petr Viktorin <[email protected]>
Co-authored-by: T. Wouters <[email protected]>
Co-authored-by: Hugo van Kemenade <[email protected]>
Kronuz pushed a commit to Kronuz/cpython that referenced this pull request Oct 5, 2026
@miss-islington @pablogsal
@encukou @Yhg1s @hugovk @Kronuz
[3.15] pythongh-158140: Resolve lazily imported sibling submodules in…
bcb3aa6
…dependently (pythonGH-158521) (python#158613)

Co-authored-by: Pablo Galindo Salgado <[email protected]>
Co-authored-by: Petr Viktorin <[email protected]>
Co-authored-by: T. Wouters <[email protected]>
Co-authored-by: Hugo van Kemenade <[email protected]>
@xv1rcn xv1rcn mentioned this pull request Oct 15, 2026
gh-158597: Resolve lazy submodules with the declaration in scope #159476
Closed
xv1rcn added a commit to xv1rcn/cpython that referenced this pull request Oct 15, 2026
@xv1rcn
pythongh-158597: Resolve lazy submodules with the declaration in scope
00db886
A pending child in `lazy_pending_submodules` is keyed only by
`(parent, child)`, so a later declaration of the same name by another module
replaces the earlier one. Resolving the child then copies the location out of
the surviving declaration, so the chained `ImportError` points into the file
of a module that merely declared the name.

Key the declarations by the declaring module, and select one from the frame's
globals at access time, so the child resolves with the declaration in scope
where the access is written. A declaration made by another module still names
the same child and imports the same thing, so it is still used when there is
nothing in scope; its location is then not reported as a frame of the
accessing module's traceback.

The selection also decides which `__import__` runs, since
`_PyLazyImport_LoadChild()` takes `lz_builtins` from the declaration it is
given. An access that has a declaration of its own in scope now uses that
module's hook instead of the last-registered one's — the case Yhg1s described
in the pythongh-158521 review. An access with no declaration in scope is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@encukou encukou encukou left review comments
@Yhg1s Yhg1s Yhg1s approved these changes
@DinoV DinoV Awaiting requested review from DinoV DinoV is a code owner
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner
@brettcannon brettcannon Awaiting requested review from brettcannon brettcannon is a code owner
@ncoghlan ncoghlan Awaiting requested review from ncoghlan ncoghlan is a code owner
@warsaw warsaw Awaiting requested review from warsaw warsaw is a code owner
@FFY00 FFY00 Awaiting requested review from FFY00 FFY00 is a code owner
@kumaraditya303 kumaraditya303 Awaiting requested review from kumaraditya303 kumaraditya303 is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

release-blocker

Projects

Release and Deferred blockers 🚫
Status: Done

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Accessing one lazily imported submodule (lazy import pkg.a) also imports a later imported pkg.b

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@pablogsal @Yhg1s @bedevere-bot @encukou @hugovk
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.