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

史提芬

我正在__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上对的调用工作正常。

aught

这是python2与python3之间的区别。

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

在python2中,importlib.import_module调用到此结束,这是对内置__import__模块的调用,该内置模块可能直接在module上操作__dict__

唯一的问题是它在python3中到底是如何工作的。我本以为它总是会导致错误AttributeError

只要执行以下操作,您的代码就可以正常工作.setter

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

事实证明,.setter可以执行任何操作,包括pass因为您无条件调用import_module

我会考虑使用.setattr上述方法并将吸气剂更改为:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TOP 榜单

热门标签

归档