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

如何用Python asyncio限制并发?相关技术问题咨询

回答

问题1:更高效地等待所有下载任务完成

你现在用固定等待9秒的方式确实不够灵活,毕竟实际下载时长是随机的,很容易出现等早了任务没跑完或者等久了浪费时间的情况。其实你可以保存所有创建的任务引用,然后用asyncio.gather()或者asyncio.wait()来等待所有任务完成,这才是异步编程里的标准做法。

修改后的main函数可以这样写:

async def main(loop):
    global count
    permit_download = asyncio.Event()
    permit_download.set()
    downloading_event = asyncio.Event()
    no_concurrent = 3
    i = 0
    tasks = []  # 用来存储所有任务引用
    while i < 9:
        if permit_download.is_set():
            count += 1
            if count >= no_concurrent:
                permit_download.clear()
            task = loop.create_task(download(i, permit_download, no_concurrent, downloading_event))
            tasks.append(task)  # 添加到任务列表
            await downloading_event.wait()
            downloading_event.clear()
            i += 1
        else:
            await permit_download.wait()
    await asyncio.gather(*tasks)  # 等待所有任务完成

这样就不需要靠猜时长来等待了,asyncio.gather()会自动等到所有传入的任务都执行完毕才继续往下走,完全贴合你的需求。

另外,其实你还可以用**信号量(Semaphore)**来简化并发控制的逻辑,不需要自己维护count和permit_download事件,Semaphore本身就可以限制同时运行的任务数,代码会更简洁:

from random import randint
import asyncio

async def download(code, semaphore):
    async with semaphore:
        wait_time = randint(1, 3)
        print('downloading {} will take {} second(s)'.format(code, wait_time))
        await asyncio.sleep(wait_time)
        print('downloaded {}'.format(code))

async def main():
    no_concurrent = 3
    semaphore = asyncio.Semaphore(no_concurrent)
    tasks = [download(i, semaphore) for i in range(9)]
    await asyncio.gather(*tasks)

if __name__ == '__main__':
    asyncio.run(main())

用Semaphore的方式不仅去掉了全局变量和复杂的事件控制,还能更优雅地实现最多3个并发下载的需求,同时自然地等待所有任务完成。

问题2:类似JavaScript async库的Python异步工具库

Python生态里有不少专门处理异步模式的优秀库,推荐几个常用的:

  • aiojobs:专门用来管理异步任务的库,支持任务的批量创建、取消、超时控制,很适合处理类似你这种需要控制并发数的场景,用法比原生的更简洁。
  • tenacity:专注于重试逻辑的库,不管是同步还是异步代码都能轻松添加重试机制,比如下载失败自动重试,配置非常灵活。
  • asyncstdlib:提供了很多类似标准库但支持异步的工具函数,比如异步版本的map、filter、reduce,让你在异步代码里也能像写同步代码一样处理迭代器。
  • anyio:一个兼容性很强的异步库,同时支持asyncio和trio两种异步框架,提供了很多高级的异步工具,比如任务组、超时管理、并发限制等,适合需要跨框架兼容的场景。

这些库都能帮你简化异步代码的编写,解决常见的异步编程痛点,和JavaScript里的async库功能类似。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:45:33