You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python协程未按预期0.5秒间隔执行的原因排查

问题:协程任务未按预期间隔执行

我有一个按特定频率触发事件的函数,以及作为动作的协程任务。以下是我的实现(wrapper函数),但协程似乎同时运行,请问这是怎么回事?

import time
import asyncio
start = time.time()

def main(callback):
    for i in range(5):
        time.sleep(.5)
        callback()

async def sub_task():
    print("sub_task", time.time() - start)


#-----------------------
# 以下是我的实现
def wrapper():
    asyncio.create_task(sub_task())

main(wrapper)

# 输出:为什么它们不是按0.5秒间隔执行?
#sub_task 2.57704758644104
#sub_task 2.57704758644104
#sub_task 2.57704758644104
#sub_task 2.5780487060546875
#sub_task 2.5780487060546875

注:代码在干净的Jupyter Notebook中测试。


原因分析

核心问题是你混用了同步阻塞代码和异步协程,且没有正确调度事件循环:

  1. main里的time.sleep(.5)是同步阻塞调用,会直接卡住整个线程,这段时间内asyncio的事件循环完全无法运行。
  2. asyncio.create_task()只是把协程加入事件循环的任务队列,但此时事件循环未启动,所有任务都处于待执行状态。
  3. 直到main函数执行完毕(总共阻塞2.5秒),Jupyter后台的事件循环才会接管,一次性跑完所有待执行的sub_task,所以所有输出时间几乎一致。

解决方案

方案1:同步环境中手动调度事件循环

如果必须保留main同步函数,可以在每次创建任务后,手动让事件循环执行该协程:

def wrapper():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(sub_task())

这样每次调用wrapper时,会同步等待sub_task执行完成,输出会按0.5秒间隔出现。

方案2:完全改用异步代码(推荐)

把同步的main改成异步函数,用asyncio.sleep()替代time.sleep(),让事件循环正常调度任务:

import time
import asyncio
start = time.time()

async def main():
    for i in range(5):
        await asyncio.sleep(.5)
        asyncio.create_task(sub_task())

async def sub_task():
    print("sub_task", time.time() - start)

asyncio.run(main())

asyncio.sleep()不会阻塞事件循环,每次等待0.5秒后创建的任务会被及时调度,输出时间会符合预期间隔。


内容的提问来源于stack exchange,提问作者qing6010

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:32:44