gpt4 book ai didi

python - 延迟加载 python 子模块,importlib 第一次失败

转载 作者:行者123 更新时间:2023-11-28 18:10:41 25 4
gpt4 key购买 nike

我正在尝试在包的 __init__.py 中延迟加载符号的想法。通过子类化 ModuleType并为每个子模块定义属性。访问包命名空间中的符号将触发导入。我让它工作了,但出于某种原因,我调用 import_module第一次尝试失败,我不明白为什么。

我有一个最小的例子。假设这样一个包:

my_package:
__init__.py
m1.py

这是__init__.py

import sys
import importlib
from types import ModuleType


class MyModule(ModuleType):
@property
def m1(self):
try:
_m1 = importlib.import_module('.m1', __package__)
except AttributeError:
print('second try ...')
_m1 = importlib.import_module('.m1', __package__)

return _m1


old = sys.modules[__name__]
new = MyModule(__name__)
new.__path__ = old.__path__

for k, v in list(old.__dict__.items()):
new.__dict__[k] = v

sys.modules[__name__] = new

import_module调用总是失败并显示 AttributeError: module 'my_package' has no attribute 'm1' .但是,第二次调用总是成功。换句话说,当我做 my_package.m1我总是得到 m1 , 但它总是打印 'second try ...' .

请注意,行为取决于 python 版本。调用import_lib第一次在 python2.7 上运行良好。

最佳答案

这是 python2 和 python3 之间的区别。

在 python3 中,importlib.import_module 调用最终结束 here这是对 setattr 的调用。由于您没有为 .setter 定义您的属性,您会得到 AttributeError

在 python2 中,importlib.import_module 调用结束 here这是对内置 __import__ 的调用,它可能会运行直接在模块 __dict__ 上。

唯一的问题是它在 python3 中究竟是如何工作的。我会认为它会总是导致AttributeError

只要你制作一个 .setter,你的代码就可以正常工作:

@m1.setter
def m1(self, mod):
self.__dict__['m1'] = mod

事实证明 .setter 可以做任何事情,包括 pass 因为您无条件地调用电话导入模块

我会考虑使用上面的 .setattr 并将 getter 更改为:

@property
def m1(self):
if not self.__dict__.get('m1'):
self.__dict__['m1'] = importlib.import_module('.m1', __package__)
return self.__dict__['m1']

关于python - 延迟加载 python 子模块,importlib 第一次失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50901109/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com