Python 惰性导入的项目实践

 更新时间:2026年04月08日 08:59:36   作者:RockByte  
Python3.15引入了lazyimports特性,允许在导入模块时延迟执行,从而避免启动阶段的高成本导入,本文就来详细的介绍一下惰性导入的项目实践,感兴趣的可以了解一下

不用再等待慢吞吞的模块加载,也不用继续依赖临时性的绕路写法:Python 3.15 新特性 —— lazy imports 机制已经给出了更直接的解法。

我们知道,在 Python 中导入模块时,解释器必须先把这个模块的代码完整求值,程序才能继续往下执行。

对大多数模块来说,听起来没什么问题。

但如果某个模块的启动过程很长、很重,那么程序就会在导入它的那一刻被拖慢。

以前,Python 开发者通常会通过调整导入位置来绕开这个问题,让导入只在真正需要时才发生。

最常见的做法就是把 import 放进函数体里,而不是写在模块顶层。

不过,这终究是一种不太优雅的权宜之计,也会让程序流程变得更难梳理。

Python 3.15 引入了一个新特性:lazy imports

它为加载缓慢的模块提供了一种更高层次、也更正式的解决方案。

当一次导入被声明为“惰性”时,它不会在第一次导入时立刻求值,而是等到第一次真正被使用时才求值。

这样一来,慢速导入的成本就可以被推迟到真正需要那段代码的时候再支付。

而且,虽然惰性导入带来了新语法,你依然可以提前让现有代码适配它,而不必大面积改写既有的导入语句。

立即与惰性

要理解惰性导入解决了什么问题,最好的方式还是先看一个例子。

开发者应该经常这样写代码,假设同一个目录下有这样两个文件:

# main.py
print("Program starting")
from other import some_fn
print("Other module imported")
some_fn()
print("Program ended")
# other.py
print("Other module evaluation started")
from time import sleep
sleep(2)
# ^ This simulates a slow-loading module
print("Other module evaluation ended")
def some_fn():
    print("some_fn run")

如果运行 main.py,输出大概会是这样:

Program starting
Other module evaluation started
[two-second delay]
Other module evaluation ended
Other module imported
some_fn run
Program ended

仅仅因为导入了 other,程序就几乎被卡住了。

甚至在我们真正调用导入进来的函数之前,更别说继续执行后续逻辑之前,这段等待就已经发生了。

现在把 main.py 改成使用惰性导入,再看看会发生什么。

这只适用于 Python 3.15 或更高版本。

print("Program starting")
lazy from other import some_fn
print("Other module imported")
some_fn()
print("Program ended")

这时再运行程序,行为就会发生变化:

Program starting
Other module imported
Other module evaluation started
[two-second delay]
Other module evaluation ended
some_fn run
Program ended

现在,导入本身已经不会造成任何延迟。

真正的等待,只有在我们调用那个导入进来的函数时才会出现。

那底层到底做了什么?

当 Python 识别到惰性导入时,通常是因为导入语句前面出现了 lazy 关键字,就像上面的例子那样,它不会走平常的导入流程。

取而代之的是,它会为被导入的模块创建一个“代理对象”,也就是一个占位用的替身。

这个代理会一直待命,直到程序真的开始对这个模块做某些操作。

到了那一刻,真正的导入才会触发,模块也才会被求值。

如果你想把某一行导入声明成惰性导入,那么 lazy 必须始终是该行的第一个词:

# lazily imports foo
lazy import foo
# lazily imports bar from foo
lazy from foo import bar
# same with the use of "as":
lazy import foo as foo1
lazy from foo import bar as bar1

用在哪里

惰性导入最常见的用途,就是替代那些为了避免启动阶段高成本导入而写出来的传统变通方案。

正如前面提到的,把导入写在函数内部而不是模块顶层,的确能让导入只在函数执行时才发生。

但这样做也带来了另一个问题:这个导入只存在于函数作用域内。

因此,除非你再叠加另一层绕路方案,否则模块里的其他代码都没法直接使用它。

而使用惰性导入后,你依然可以把导入保留在模块顶层,就像平常那样写。

你唯一需要做的,只是在代码前面加上 lazy 关键字。

自动启用惰性导入

你还可以在现有代码库里自动启用惰性导入,而不必逐条改写 import 语句。

Python 3.15 为 sys 模块新增了一些能力,用来控制惰性导入的行为。

例如,你可以通过编程方式声明:从程序执行的某个时间点开始,之后所有导入都采用惰性方式处理。

import sys
sys.set_lazy_imports("all")

如果给 sys.set_lazy_imports() 传入 "all",那么从那一刻起,程序中的每一次导入都会变成惰性导入,不管它是否显式写了 lazy 关键字。

如果(给该函数)传入 "normal",则只有显式声明的才会惰性导入

如果传入 "none",则彻底关闭惰性导入。

以编程方式控制惰性导入

你也可以在运行时接管惰性导入的行为。

这样一来,你就能够进一步控制到底哪些模块会被惰性导入。

import sys
def mod_filter(importing, imported, fromlist):
    return imported == "module"
sys.set_lazy_imports_filter(mod_filter)

sys.set_lazy_imports_filter() 允许你传入一个函数,这个函数会接收三个参数:

  • 发起导入的模块
  • 被导入的模块
  • 被导入名称组成的列表

借助这个函数,你可以写出自己的判断逻辑:返回 True 时,允许某次导入按惰性方式进行;返回 False 时,则强制它按普通方式立即导入。

这样,你既可以在测试里为惰性导入维护允许列表和阻止列表,也可以把这套规则直接纳入程序自身的运行机制。

使用惰性导入的两种方式

Python 一直以来都很重视让新特性能平滑进入已有代码库。

惰性导入同样可以按这种方式接入。

你可以在程序启动时先检查这个能力是否存在,然后再通过 sys.set_lazy_imports() 自动把惰性导入应用到整个项目中。

最直接的办法,是先判断 Python 版本号:

import sys
if sys.version_info >= (3, 15):
    ...  # set up lazy imports

或者,也可以直接检查 sys 中是否提供了这些惰性导入控制接口:

import sys
if hasattr(sys, "set_lazy_imports"):
    ...  # set up lazy imports

到此这篇关于Python 惰性导入的项目实践的文章就介绍到这了,更多相关Python 惰性导入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中__new__()方法适应及注意事项详解

    Python中__new__()方法适应及注意事项详解

    这篇文章主要介绍了Python中__new__()方法适应及注意事项的相关资料,new()方法是Python中的一个特殊构造方法,用于在创建对象之前调用,并负责返回类的新实例,它与init()方法不同,需要的朋友可以参考下
    2025-03-03
  • python实现监控某个服务 服务崩溃即发送邮件报告

    python实现监控某个服务 服务崩溃即发送邮件报告

    这篇文章主要为大家详细介绍了python实现监控某个服务,服务崩溃发送邮件报告,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Python yield 关键词,

    Python yield 关键词,

    这篇文章主要介绍了Python yield 关键词,要理解yield的作用,你必须理解生成器是什么。在理解生成器之前,必须先理解迭代器。下面文章我们就先从
    迭代器开始展开yield关键词的相关自资料 ,需要的朋友可以参考一下
    2021-12-12
  • pandas 数据实现行间计算的方法

    pandas 数据实现行间计算的方法

    今天小编就为大家分享一篇pandas 数据实现行间计算的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • Python实现GPU加速图像处理的代码详解

    Python实现GPU加速图像处理的代码详解

    这篇文章主要为大家详细介绍了Python实现GPU加速图像处理的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • python sqlite的Row对象操作示例

    python sqlite的Row对象操作示例

    这篇文章主要介绍了python sqlite的Row对象操作,结合实例形式分析了Python使用sqlite的Row对象进行数据的查询操作相关实现技巧,需要的朋友可以参考下
    2019-09-09
  • 一篇文章学会两种将python打包成exe的方式

    一篇文章学会两种将python打包成exe的方式

    最近有部分小伙伴问我,python 写的项目可不可以打包成exe程序,放到没有python环境上的电脑中执行? 答案当然是可以的,下面这篇文章主要给大家介绍了如何通过一篇文章学会两种将pyton打包成exe的方式,需要的朋友可以参考下
    2021-11-11
  • 如何用python GUI(tkinter)写一个闹铃小程序(思路详解)

    如何用python GUI(tkinter)写一个闹铃小程序(思路详解)

    这篇文章主要介绍了用python GUI(tkinter)写一个闹铃小程序思路详解,涉及到tkinter一些函数控件,数据的类的封装,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2021-12-12
  • 详解Python中对Excel的处理操作

    详解Python中对Excel的处理操作

    Excel是一种常见的电子表格文件格式,广泛用于数据记录和处理,Python提供了多个第三方库,可以方便地对Excel操作,下面就来和大家详细讲讲吧
    2023-07-07
  • Win下PyInstaller 安装和使用教程

    Win下PyInstaller 安装和使用教程

    pyinstaller是一个非常简单的打包python的py文件的库,这篇文章主要介绍了PyInstaller-Win安装和使用教程,本文通过流程实例相结合给大家介绍的非常详细,需要的朋友可以参考下
    2019-12-12

最新评论