繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM