LazyImportType.resolve() does not replace the module global and can import twice
未关闭
还没有人认领这个 Issue。
interpreter-core
topic-lazy-imports
type-bug
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 35.9k
- PR 合并指标
- PR 指标待抓取
描述
Bug report
Bug description:
Calling resolve() on a lazy import proxy forces the import and returns the resolved object, but it does not replace the original lazy object in the module globals. A later normal global access reifies the same lazy object again.
import builtins
import types
real_import = builtins.__import__
calls = []
lazy import target_module as target
def custom_import(name, globals=None, locals=None, fromlist=None, level=0):
if name == "target_module":
index = len(calls) + 1
calls.append((index, name, globals.get("__name__"), fromlist))
module = types.ModuleType(name)
module.VALUE = f"value-{index}"
return module
return real_import(name, globals, locals, fromlist, level)
builtins.__import__ = custom_import
try:
def resolve_from_dict():
lazy_obj = globals()["target"]
resolved = lazy_obj.resolve()
print("resolved:", resolved.VALUE)
print("global after resolve:", type(globals()["target"]).__name__)
resolve_from_dict()
print("direct:", target.VALUE)
print("global after direct:", type(globals()["target"]).__name__)
print("calls:", calls)
finally:
builtins.__import__ = real_import
Expected: one import, with the module global replaced after resolve().
Actual on current main:
resolved: value-1
global after resolve: lazy_import
direct: value-2
global after direct: module
calls: [(1, 'target_module', '__main__', None), (2, 'target_module', '__main__', None)]
I confirmed this across tier1, tier2, and tier2 without uop optimization:
https://github.com/Kuhai9801/cpython/actions/runs/28243825007
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-152308
- gh-152524
- gh-157730
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 issue 中的 reproducer 开始,跟踪 LazyImportType.resolve(),重点关注 lazy 对象如何存储在模块全局变量中。当 resolve() 导致一次 import、替换模块全局变量,并且之后的直接访问返回同一个模块时,即表示完成;根据所示的调用和输出进行验证。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- backend
- Issue 类型
- 缺陷
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 活跃度
- 停滞
- 描述清晰度
- 描述清楚
- 新手友好度
- 30/100