在Python中,模块导入通常是在程序开始时进行的,这意味着一旦模块被导入,其相关的代码和资源就会被加载到内存中,直到程序结束。尽管这在大多数情况下都能正常工作,但在处理大型项目或具有复杂依赖关系的代码时,这种"早期导入"的方式可能会导致不必要的内存使用和启动延迟。本文记录 Python 在 import 时常用的懒加载实现方案。
简介 {#简介}
为了解决这个问题,Python提供了惰性导入的概念,即在真正需要时才导入模块。这可以通过几种方式实现,包括使用 importlib
模块、使用 __import__
函数、以及使用延迟执行的技术(如lambda函数或装饰器)。
_LazyModule {#LazyModule}
https://github.com/huggingface/diffusers
huggingface
包的组织方式中出现了 _LazyModule
,这个模块实际上对应了python中的一种lazy import的思想。也就是在整个包很大的情况下不再将所有的包都import,而仅仅在使用的时候进行真正的import。这么做可以极大地缩短整个的import时间。
核心实现 {#核心实现}
源码链接: https://github.com/huggingface/diffusers/blob/main/src/diffusers/utils/import_utils.py
使用方法 {#使用方法}
首先看一下最高层的包是如何调用这个 lazy import
类的,也就是package_name下的 __init__.py
:
我们首先用了一个字典将我们想要导入的东西包起来,然后一起喂给_LazyModule,最后由_LazyModule传给sys.modules
这个包起来的东西包含了根目录的下级目录,extend的部分是我们最终想要导入的东西。流程是这样:
我们想要一个名为a的东西,那么packge就会去找下级目录找a,如果下级目录能够找到a,那么显然可以直接 from XX import a
。但是问题出在下级目录显然也没有 a
,下级目录又要到下下级目录中去找,直至找到。我们不妨看看叶子的 __init__.py
总结:
我们通过from XX import a,python有如下操作
从 XX 中要a,XX再找pipelines要a,pipelines再找foo要a,foo再找bar要a,最终要到了a。
这么一来,from XX import a, from XX.pipelines import a, from XX.pipelines.foo import a, from XX.pipelines.foo.bar import a,全部都是可用的。
TensorFlow {#TensorFlow}
Tensorflow 的 LazyLoad 方案:
核心实现 {#核心实现-2}
使用方法 {#使用方法-2}
- 代码说明:
类 LazyLoader 继承自 types.ModuleType,初始化函数确保惰性模块将像真正的模块一样正确添加到全局变量中,只要真正用到模块的时候,也就是执行 getattr 或 dir 时,才会真正的 import 实际模块,更新全局变量以指向实际模块,并且将其所有状态( dict )更新为实际模块的状态,以便对延迟加载的引用,加载模块不需要每次访问都经过加载过程。
- 代码使用:
正常情况下我们这样导入模块:
其对应的惰性导入版本如下:
Python 原生实现 {#Python-原生实现}
importlib
{#importlib}
importlib
是Python标准库中的一个模块,提供了动态导入模块的功能。通过 importlib.import_module
函数,可以在运行时按需导入模块。
__import__
{#import}
__import__
是一个内置函数,其行为类似于 import
语句。它接受模块名作为字符串,并返回导入的模块对象。
lambda函数 {#lambda函数}
另一种实现惰性导入的方法是使用延迟执行的技术,如lambda函数。
装饰器 {#装饰器}
装饰器是另一种延迟执行技术的实现
LazyLoader {#LazyLoader}
importlib.util
中的 LazyLoader
可以懒加载。
目录结构
impt.py
a.py
执行并查看输出结果
参考资料 {#参考资料}
- https://cloud.baidu.com/article/3296561
- https://blog.csdn.net/weixin_43590796/article/details/134945144
- https://www.51cto.com/article/720765.html
- https://www.cnblogs.com/lyg-blog/p/14806886.html
文章链接:
https://www.zywvvd.com/notes/coding/python/python-lazy-load/python-lazy-load/