Python实现自动启用惰性导入的实战指南

 更新时间:2026年04月07日 09:11:27   作者:RockByte  
Python 3.15 引入了一个新特性:lazy imports(惰性导入),它为加载缓慢的模块提供了一种更高层次、也更正式的解决方案,下面小编就和大家详细介绍一下如何在Python中动启用惰性导入吧

不用再等待慢吞吞的模块加载,也不用继续依赖临时性的绕路写法: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惰性导入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入解析pandas数据聚合和重组

    深入解析pandas数据聚合和重组

    这篇文章主要介绍了pandas数据聚合和重组,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Python字符串和正则表达式中的反斜杠(''\'')问题详解

    Python字符串和正则表达式中的反斜杠(''\'')问题详解

    在本篇文章里小编给大家整理的是关于Python字符串和正则表达式中的反斜杠('\')问题以及相关知识点,有需要的朋友们可以学习下。
    2019-09-09
  • pytorch使用Variable实现线性回归

    pytorch使用Variable实现线性回归

    这篇文章主要为大家详细介绍了pytorch使用Variable实现线性回归,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • pygame实现一个类似满天星游戏流程详解

    pygame实现一个类似满天星游戏流程详解

    这篇文章主要介绍了使用pygame来编写类满天星游戏的全记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-09-09
  • 使用 django orm 写 exists 条件过滤实例

    使用 django orm 写 exists 条件过滤实例

    这篇文章主要介绍了使用 django orm 写 exists 条件过滤实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • python爬虫基本知识

    python爬虫基本知识

    最近在做一个项目,这个项目需要使用网络爬虫从特定网站上爬取数据,于是乎,我打算写一个爬虫系列的文章,与大家分享如何编写一个爬虫。下面这篇文章给大家介绍了python爬虫基本知识,感兴趣的朋友一起看看吧
    2018-03-03
  • pygame实现俄罗斯方块游戏(基础篇1)

    pygame实现俄罗斯方块游戏(基础篇1)

    这篇文章主要为大家介绍了pygame实现俄罗斯方块游戏基础的第1篇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • Python使用PyMySql增删改查Mysql数据库的实现

    Python使用PyMySql增删改查Mysql数据库的实现

    PyMysql是Python中用于连接MySQL数据库的一个第三方库,本文主要介绍了Python使用PyMySql增删改查Mysql数据库的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Python中4种实现数值的交换方式

    Python中4种实现数值的交换方式

    这篇文章主要介绍了Python中4种实现数值的交换方式,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • python模拟投掷色子并数据可视化统计图

    python模拟投掷色子并数据可视化统计图

    这篇文章主要介绍了python模拟投掷色子并数据可视化统计图,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07

最新评论