事件循环
约 731 字大约 2 分钟
2026-08-22
同步代码的问题
import requests
def task1():
# 任务1
requests.post(...) # 发送请求,阻塞线程
def task2():
# 任务2
pass
task1() # task1的阻塞导致后续任务白白等待,浪费了CPU资源
task2()什么是异步
异步是一种编程模式,当有多个任务需要在一个线程上执行时,这种模式可以让任务不会造成线程阻塞
异步 VS 多线程
运算密集型:多线程
I/O密集型:异步
Python的事件循环
事件循环是实现异步的基础手段
AbstractEventLoop类
在python中,一个事件循环就是一个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方法
def run_forever(self):
"""Run until stop() is called."""
while True:
self._run_once()
if self._stopping:
break_run_once逻辑
_run_once方法的核心,就是调度事件循环中的队列
它要确保每次该方法运行,都能保证ready队列中的所有回调得到执行
- 检查延时队列,加入ready
- 计算等待时间 timeout
- ready有东西,timeout = 0
- 延时队列还有任务,timeout = 延时队列的队首 - 当前时间
- 都没有任务,timeout = None
- 用timeout的时间阻塞线程,等待I/O,期间有任何IO任务到达,马上加入ready
- 如果timeout时间到达后还没有I/O任务,则重新处理一次延时队列
- 复制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("事件循环已停止")作业
一、预测以下代码的输出结果
import asyncio
loop = asyncio.new_event_loop()
def task1():
print("任务1")
def task2():
print("任务2")
def task3():
print("任务3")
loop.call_soon(task1)
print("task1 over")
loop.call_soon(task2)
print("task2 over")
loop.call_soon(task3)
print("task3 over")
loop.run_forever()
print("已结束")二、预测以下代码的输出结果
import asyncio
loop = asyncio.new_event_loop()
def delayed():
print(1)
loop.call_later(0, lambda: print(2))
loop.call_soon(lambda: print(3))
def soon():
print(4)
loop.call_soon(lambda: print(5))
loop.call_later(0, delayed)
loop.call_soon(soon)
loop.run_forever()
print("done")三、预测以下代码的输出结果
import asyncio
loop = asyncio.new_event_loop()
def first():
print(1)
def second():
print(2)
loop.call_soon(lambda: print(3))
loop.stop()
def third():
print(4)
loop.call_soon(first)
loop.call_soon(second)
loop.call_soon(third)
loop.run_forever()
print("循环已停止")