当前位置:首页>python>Python 并发与 asyncio 14.3 强制事件循环迭代

Python 并发与 asyncio 14.3 强制事件循环迭代

  • 2026-08-24 14:29:05
Python 并发与 asyncio 14.3 强制事件循环迭代

14.3 强制事件循环迭代

事件循环的内部运作机制对我们来说基本是黑盒,它自行决定何时以及如何执行协程和任务。不过,如果真有需要,我们也可以手动触发一次事件循环的迭代。这在某些场景下很有用,比如让一个耗时很长的任务尽早开始,避免阻塞整个事件循环(但这种情况下也应考虑使用线程),或者确保某个任务能够立刻启动。

回想一下,当我们创建多个任务时,它们都不会立即开始执行,直到遇到一个 await 点。这个 await 会触发事件循环去调度和启动这些任务。但如果我们希望每一个任务都立刻就开始运行,该怎么办呢?

asyncio 提供了一个优化的惯用法:向 asyncio.sleep(0) 传入零,来挂起当前协程并强制进行一次事件循环迭代。我们来看看怎么用这个技巧来尽快启动任务。我们要写两个函数,一个不用 sleep,一个用,来对比它们的执行顺序。

import asynciofrom util import delayasync def create_tasks_no_sleep():    task1 = asyncio.create_task(delay(1))    task2 = asyncio.create_task(delay(2))    print('Gathering tasks:')    await asyncio.gather(task1, task2)async def create_tasks_sleep():    task1 = asyncio.create_task(delay(1))    await asyncio.sleep(0)    task2 = asyncio.create_task(delay(2))    await asyncio.sleep(0)    print('Gathering tasks:')    await asyncio.gather(task1, task2)async def main():    print('--- Testing without asyncio.sleep(0) ---')    await create_tasks_no_sleep()    print('--- Testing with asyncio.sleep(0) ---')    await create_tasks_sleep()asyncio.run(main())

运行上面的代码,你会看到这样的输出:

--- Testing without asyncio.sleep(0) ---Gathering tasks:sleeping for 1 second(s)sleeping for 2 second(s)finished sleeping for 1 second(s)finished sleeping for 2 second(s)--- Testing with asyncio.sleep(0) ---sleeping for 1 second(s)sleeping for 2 second(s)Gathering tasks:finished sleeping for 1 second(s)finished sleeping for 2 second(s)

首先,我们创建了两个任务,然后直接 gather 它们,没有用 asyncio.sleep(0)。这是预期的结果,两个 delay 协程直到 gather 语句才开始执行。接着,我们在每次创建任务后都插入了一个 asyncio.sleep(0)。在输出中,你会注意到 delay 协程的消息会在调用 gather 之前就立即打印出来。这是因为 sleep(0) 触发了一次事件循环迭代,导致我们任务里的代码立刻就执行了。

我们现在主要用的是 asyncio 自带的事件循环实现。但其实还有别的实现方式可供替换。接下来,我们来看看如何使用不同的事件循环。

最新文章

随机文章