先抛开代码,用一个生活例子理解。
厨师的故事
想象你是一个厨师(= 事件循环),厨房里同时有好几个订单要做。
同步的做法(笨办法)
- 订单 1:煮一锅汤,要炖 30 分钟
→ 你站在灶台前干等 30 分钟,什么都不干 - 汤好了,再看订单 2:切菜
- 订单 3:炒菜……
问题很明显:等汤的时候手是闲着的,但后面的订单全被堵住了。
对应到代码:
import requests def task1(): # 任务1 requests.post(...) # 发送请求,阻塞线程 def task2(): # 任务2 pass task1() # task1的阻塞导致后续任务白白等待,浪费了cpu资源 task2()
异步的做法(聪明的办法)
- 订单 1:把汤放上灶,设个闹钟,然后去干别的
- 订单 2:切菜
- 订单 3:炒菜
- 闹钟响了 → 回去看汤好了没 → 好了就盛出来
你还是一个人,但通过「不傻等」,同时推进了好几个任务。
对应到代码
| 生活中的角色 | 代码中的角色 |
|---|---|
| 厨师 | 事件循环(event loop) |
| 订单 | 任务(回调函数) |
| 设闹钟 | call_later(秒数, 回调) |
| 「马上做」 | call_soon(回调) |
| 闹钟响了 / 汤好了 | 任务进入 ready 队列,可以被执行 |
所以事件循环的工作就一句话:
反复检查:有没有该做的事?有就做,没有就等。
两个队列(两个篮子)
事件循环手里有两个「篮子」:
- ready 篮子(就绪队列):马上就能做的任务
- 延时篮子(延时队列):还没到时间的任务,先放这儿
每轮循环做的事:
- 看看延时篮子里有没有到时间的 → 有就挪到 ready 篮子
- 把 ready 篮子里的任务全部做完
- 回到第 1 步
最简单的理解
事件循环 = 一个永远在转的轮子
= 每转一圈,看看有没有该做的事
= 有就做,没有就等
= 直到有人喊「停」(loop.stop())python 里怎么写
abstracteventloop 类
一个事件循环,就是一个 abstracteventloop 对象:
import asyncio
# 创建一个新的事件循环对象
loop = asyncio.new_event_loop()
# 绑定事件循环到当前线程
asyncio.set_event_loop(loop)
# 获取当前线程的事件循环
current_loop = asyncio.get_event_loop()
print("当前事件循环:", current_loop)
# 移除事件循环绑定
asyncio.set_event_loop(none)
# 运行事件循环
# 陷入死循环,除非在循环中终止,否则后续代码永远无法得到运行
current_loop.run_forever()
# 停止事件循环
current_loop.stop()
run_forever:让轮子转起来
本质就是一个 while true:不停跑,直到有人调用 stop():
def run_forever(self):
"""run until stop() is called."""
while true:
self._run_once()
if self._stopping:
break
_run_once:每一圈具体做什么
- 检查延时队列 → 到期的挪进 ready
- 计算要等多久(timeout)
- ready 里已有任务 → timeout = 0(立刻继续)
- 延时队列还有任务 → timeout = 队首到期时间 - 现在
- 两边都空 → timeout = none(一直等到有 i/o)
- 用 timeout 阻塞等待 i/o;期间有 i/o 就绪,立刻放进 ready
- 若等到超时仍无 i/o,再处理一次延时队列
- 复制一份 ready 队列
- 执行这份复制出来的回调
本质上就是一个 while true 不断重复这几步。
试一试
- call_soon(回调) → 「马上做」,放进 ready
- call_later(秒数, 回调) → 「设闹钟」,先放延时队列,到期再进 ready
import inspect
import asyncio
loop = asyncio.new_event_loop()
# 将函数直接放入ready队列
def my_ready_callback():
print("这是一个直接进入ready队列的回调函数")
loop.call_soon(my_ready_callback)
# 将函数放入延迟队列,1秒后进入ready队列
def my_scheduled_callback():
print("这是一个延迟1秒后进入ready队列的回调函数")
loop.stop() # 停止事件循环
loop.call_later(1, my_scheduled_callback)
loop.run_forever()
print("事件循环已停止")
到此这篇关于python中事件循环的实现示例的文章就介绍到这了,更多相关python 事件循环内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论