Python中的事件循环是什么?事件是怎么个事件?循环是怎么个循环

news2025/5/11 10:26:44

在Python异步编程中,事件循环(Event Loop)是核心机制,它通过单线程实现高效的任务调度和I/O并发处理。本文将从事件的定义循环的运行逻辑以及具体实现原理三个维度展开分析。


一、事件循环的本质:协程与任务的调度器

事件循环是一个无限运行的循环结构,负责管理异步任务的执行顺序和资源分配。其核心功能包括:

  1. 调度协程:将协程封装为Task对象,按优先级执行(如asyncio.create_task())。
  2. 处理I/O事件:监听文件描述符、网络套接字等,当数据就绪时触发回调。
  3. 管理定时器:通过call_later()asyncio.sleep()实现延迟任务。

与多线程不同,事件循环通过非阻塞式切换(由await触发)实现并发,避免了线程间锁的复杂性。


二、“事件”的构成:触发与响应的单元

事件循环中的“事件”并非用户交互事件,而是异步操作的状态变更,具体分为三类:

1. I/O事件
  • 场景:网络请求、文件读写等耗时操作。
  • 机制:操作系统通过epoll/kqueue等接口通知事件循环数据是否就绪,事件循环将对应的Future标记为完成,并执行回调。
2. 定时器事件
  • 示例asyncio.sleep(2)会在事件循环的调度堆中注册一个2秒后触发的任务。
  • 底层实现:通过call_at()将任务按时间戳排序,循环检查堆顶任务是否到期。
3. 协程完成事件
  • 流程:当协程遇到await挂起时,事件循环将其状态保存,转而执行其他任务;协程完成后通过Future.set_result()通知循环恢复执行。

三、“循环”的运行逻辑:从就绪队列到调度堆

事件循环的每一轮迭代(称为一个tick)包含以下步骤:

  1. 执行就绪任务:从_ready队列中取出任务,运行至遇到await或完成。
  2. 处理I/O和定时器:通过selector检查I/O状态,从_scheduled堆中取出到期任务。
  3. 更新队列:将新就绪的任务加入_ready队列,等待下一轮调度。

代码示例:手动创建事件循环并运行协程

import asyncio

async def example_coroutine():
    print("Start")
    await asyncio.sleep(1)
    print("End")

loop = asyncio.new_event_loop()
loop.run_until_complete(example_coroutine())
loop.close()

此代码中,sleep(1)会将控制权交还事件循环,期间循环可处理其他任务。


四、事件循环的应用场景与性能优势

  1. 高并发服务器:单线程处理数千个网络连接(如Web框架FastAPI)。
  2. 密集型I/O操作:数据库查询、API调用等场景。
  3. 性能对比:相比多线程,事件循环减少了上下文切换开销,适合I/O密集型任务(但CPU密集型任务仍需多进程)。

五、与其他语言事件循环的对比

  1. JavaScript:浏览器和Node.js的事件循环分为宏任务(setTimeout)与微任务(Promise),而Python的asyncio更强调协程调度。
  2. Go:Go通过goroutinechannel实现并发,无需显式管理事件循环。

总结

Python的事件循环通过单线程+非阻塞的架构,实现了高效的异步编程模型。理解其“事件”的触发条件和“循环”的调度逻辑,是掌握asyncio库的关键。开发者可通过async/await语法编写清晰易维护的异步代码,同时结合FutureTask对象精细控制任务流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2373042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA图像处理(5)------ 图片水平镜像

利用bram形成双缓冲,如下图配置所示: wr_flag 表明 buffer0写 还是 buffer1写 rd_flag 表明 buffer0读 还是 buffer1读 通过写入逻辑控制(结合wr_finish) 写哪个buffer ;写地址 进而控制ip的写使能 通过状态缓存来跳转buffer的…

day21python打卡

知识点回顾: LDA线性判别PCA主成分分析t-sne降维 还有一些其他的降维方式,也就是最重要的词向量的加工,我们未来再说 作业: 自由作业:探索下什么时候用到降维?降维的主要应用?或者让ai给你出题&…

ERP学习(一): 用友u8安装

安装: https://www.bilibili.com/video/BV1Pp4y187ot/?spm_id_from333.337.search-card.all.click&vd_sourced514093d85ee628d1f12310b13b1e59b 我个人用vmware16,这位up已经把用友软件和环境(sqlserver2008) 都封城vmx文件了…

01 | 大模型微调 | 从0学习到实战微调 | AI发展与模型技术介绍

一、导读 作为非AI专业技术开发者(我是小小爬虫开发工程师😋) 本系列文章将围绕《大模型微调》进行学习(也是我个人学习的笔记,所以会持续更新),最后以上手实操模型微调的目的。 (本文如若有…

海康相机无损压缩

设置无损压缩得到更高的带宽和帧率!

从机器人到调度平台:超低延迟RTMP|RTSP播放器系统级部署之道

✅ 一、模块定位:跨平台、超低延迟、系统级稳定的音视频直播播放器内核 在无人机、机器人、远程操控手柄等场景中,低延迟的 RTSP/RTMP 播放器并不是“可有可无的体验优化”,而是系统能否闭环、操控是否安全的关键组成。 Windows和安卓播放RT…

研发效率破局之道阅读总结(5)管理文化

研发效率破局之道阅读总结(5)管理文化 Author: Once Day Date: 2025年5月10日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 程序的艺术_Once-Day…

单因子实验 方差分析

本文是实验设计与分析(第6版,Montgomery著傅珏生译)第3章单因子实验 方差分析python解决方案。本文尽量避免重复书中的理论,着于提供python解决方案,并与原书的运算结果进行对比。您可以从 下载实验设计与分析(第6版&a…

Bitacora:基因组组件中基因家族识别和注释的综合工具

软件教程 | Bitacora:基因组组件中基因家族识别和注释的综合工具 https://zhangzl96.github.io/tags#生物信息工具) 📅 官方地址:https://github.com/molevol-ub/bitacora 🔬 教程版本:BITACORA 1.4 📋 …

【WebRTC-13】是在哪,什么时候,创建编解码器?

Android-RTC系列软重启,改变以往细读源代码的方式 改为 带上实际问题分析代码。增加实用性,方便形成肌肉记忆。同时不分种类、不分难易程度,在线征集问题切入点。 问题:编解码器的关键实体类是什么?在哪里&什么时候…

青少年编程与数学 02-019 Rust 编程基础 01课题、环境准备

青少年编程与数学 02-019 Rust 编程基础 01课题、环境准备 一、Rust核心特性应用场景开发工具社区与生态 二、Rust 和 Python 比较1. **内存安全与并发编程**2. **性能**3. **零成本抽象**4. **跨平台支持**5. **社区与生态系统**6. **错误处理**7. **安全性**适用场景总结 三、…

Redis持久化存储介质评估:NFS与Ceph的适用性分析

#作者:朱雷 文章目录 一、背景二、Redis持久化的必要性与影响1. 持久化的必要性2. 性能与稳定性问题 三、NFS作为持久化存储介质的问题1. 性能瓶颈2. 数据一致性问题3. 存储服务单点故障4. 高延迟影响持久化效率.5. 吞吐量瓶颈 四、Ceph作为持久化存储介质的问题1.…

Ceph 原理与集群配置

一、Ceph 工作原理 1.1.为什么学习 Ceph? 在学习了 NFS 存储之后,我们仍然需要学习 Ceph 存储。这主要是因为不同的存储系统适用于不同的场景,NFS 虽然有其适用之处,但也存在一定的局限性。而 Ceph 能够满足现代分布式、大规模、…

天线的PCB设计

目录 天线模块设计的重要性 天线模块的PCB设计 天线模块设计的重要性 当智能手表突然断连、无人机信号飘忽不定——你可能正在经历一场来自天线模块的"无声抗议"。这个隐藏在电子设备深处的关键组件,就像数字世界的隐形信使,用毫米级的精密结…

C++笔记-set和map的使用(包含multiset和multimap的讲解)

1.序列式容器和关联式容器 前面我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间一般没有紧密的关联关系&#xff0…

Linux `ifconfig` 指令深度解析与替代方案指南

Linux `ifconfig` 指令深度解析与替代方案指南 一、核心功能与现状1. 基础作用2. 版本适配二、基础语法与常用操作1. 标准语法2. 常用操作速查显示所有接口信息启用/禁用接口配置IPv4地址修改MAC地址(临时)三、高级配置技巧1. 虚拟接口创建2. MTU调整3. 多播配置4. ARP控制四…

Python pandas 向excel追加数据,不覆盖之前的数据

最近突然看了一下pandas向excel追加数据的方法,发现有很多人出了一些馊主意; 比如用concat,append等方法,这种方法的会先将旧数据df_1读取到内存,再把新数据df_2与旧的合并,形成df_new,再覆盖写入,消耗和速…

【金仓数据库征文】政府项目数据库迁移:从MySQL 5.7到KingbaseES的蜕变之路

摘要:本文详细阐述了政府项目中将 MySQL 5.7 数据库迁移至 KingbaseES 的全过程,涵盖迁移前的环境评估、数据梳理和工具准备,迁移实战中的数据源与目标库连接配置、迁移任务详细设定、执行迁移与过程监控,以及迁移后的质量验证、系…

Go语言——goflow工作流使用

一、引入依赖 这个很坑,他不允许连接带密码的redis,只能使用不带密码的redis,要带密码的话得自己改一下源代码,无语 go get github.com/s8sg/goflow二、画出我们的工作流程 三、编写代码 package mainimport ("encoding/j…

yarn npm pnpm

1 下载方式 npm 之前串行下载 现在并行下载 yarn 并行下载 加入缓存复用 pnpm 硬连接 避免重复下载,先检查本地是否存在,存在的话直接连接过去