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

为何我的asyncio程序运行时长远超预期?预期8秒实际耗时14秒

问题分析与解决

你的程序实际耗时14秒,核心原因是**asyncio.gather会等待所有传入的协程任务全部完成才会结束**,而你传入的第一个任务sometask(f, 0, 2, 6, gen1)的总执行时长刚好是14秒,拖慢了整个程序的结束时间。

任务耗时拆解

我们分别计算两个任务的执行时间线:

第一个任务(gen1)

  1. 先执行await asyncio.sleep(2),耗时2秒
  2. 进入async for循环,处理第一个生成器值:
    • 写入数据后,执行await asyncio.sleep(6),耗时6秒(累计2+6=8秒)
  3. 处理第二个生成器值:
    • 写入数据后,执行await asyncio.sleep(6),耗时6秒(累计8+6=14秒)
      这个任务总耗时14秒。

第二个任务(gen2)

  1. 先执行await asyncio.sleep(0),无耗时
  2. 进入async for循环,处理第一个生成器值:
    • 写入数据后,执行await asyncio.sleep(4),耗时4秒(累计4秒)
  3. 处理第二个生成器值:
    • 写入数据后,执行await asyncio.sleep(4),耗时4秒(累计4+4=8秒)
      这个任务总耗时8秒。

因为asyncio.gather要等所有任务完成,所以程序总耗时由最长的任务决定,也就是14秒,和你的预期不符。

修正方案(如果想让总时长控制在8秒)

如果希望程序总耗时为8秒,需要调整第一个任务的sleep时长,让它的总耗时不超过8秒。比如把sleep2从6改成3:

import asyncio
import time

async def gen1():
    yield b'1a1a'
    yield b'2b2b'

async def gen2():
    yield b'3c3c'
    yield b'4d4d'

async def sometask(file, offset, sleep1, sleep2, gen):
    await asyncio.sleep(sleep1)
    async for blok in gen():
        file.seek(offset)
        file.write(blok)
        offset = file.tell()
        await asyncio.sleep(sleep2)

async def main():
    with open('file', 'wb+') as f:
        await asyncio.gather(
            sometask(f, 0, 2, 3, gen1),  # sleep2改为3
            sometask(f, 8, 0, 4, gen2))

start = time.perf_counter()

asyncio.run(main())

print(time.perf_counter()-start, 's')

此时第一个任务总耗时:2+3+3=8秒,和第二个任务耗时一致,程序总时长就会是8秒左右。

另外注意:多个协程同时操作同一个文件对象时,虽然这里用了seek指定偏移量避免覆盖,但实际场景中如果有更复杂的文件操作,建议考虑加锁(比如asyncio.Lock)避免并发写入的潜在问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:42:18