[英]Lazy loading python sub-modules, importlib fails first time
我正在通过ModuleType
并定义每个子模块的属性来试验在包的__init__.py
中延迟加载符号的想法。 访问包名称空间中的符号将触发导入。 我已经有了它的工作,但出于某种原因,我对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'
失败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
调用最终在这里结束,这是对setattr
的调用。 由于您没有为属性定义.setter
,因此您将获得AttributeError
。
在python2中, importlib.import_module
调用在这里结束,这是对builtin __import__
的调用,它可能直接在模块__dict__
。
唯一的问题是它在世界上如何在python3中运行。 我本来以为它总是导致一个AttributeError
。
只要您创建.setter
您的代码就可以正常工作:
@m1.setter
def m1(self, mod):
self.__dict__['m1'] = mod
事实证明, .setter
可以做任何事情,包括pass
因为你无条件地调用import_module
。
我会考虑使用上面的.setattr
并将getter更改为:
@property
def m1(self):
if not self.__dict__.get('m1'):
self.__dict__['m1'] = importlib.import_module('.m1', __package__)
return self.__dict__['m1']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.