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

如何使用aiohttp限制未完成的并发请求数量?

如何用aiohttp限制活跃请求数量

嘿,这个问题我太熟悉了!在aiohttp里控制同时运行的请求数量,最实用的工具就是asyncio.Semaphore——它就像一个“并发闸门”,能帮你把未完成的活跃请求数牢牢卡在设定的数值里,避免一下子发起太多请求导致服务器拒绝或者本地程序资源过载。

下面给你两种常用的解决方案,你可以根据自己的需求选:

方法一:用asyncio.Semaphore精准控制任务并发

这种方式可以单独限制图片下载任务的并发数,灵活性更高。我们只需要给你的代码加几行就行:

import asyncio
import aiohttp

async def get_images(url, session, semaphore):
    chunk_size = 100
    # 先通过信号量获取“许可”,达到限制数时会自动等待
    async with semaphore:
        print(f'Making request to {url}')
        async with session.get(url=url) as r:
            # 👉 这里要注意!原来的固定文件名会覆盖所有图片,建议改成从URL提取或用索引命名
            filename = url.split('/')[-1]
            with open(f'path/{filename}', 'wb') as file:
                while True:
                    chunk = await r.content.read(chunk_size)
                    if not chunk:
                        break
                    file.write(chunk)

async def main():
    # 设定最多同时跑5个活跃请求,数字可以根据你的需求调整
    semaphore = asyncio.Semaphore(5)
    # 你的待请求URL列表
    image_urls = [
        'https://example.com/img1.png',
        'https://example.com/img2.png',
        # ...更多URL
    ]
    async with aiohttp.ClientSession() as session:
        # 创建所有下载任务
        tasks = [get_images(url, session, semaphore) for url in image_urls]
        # 等待所有任务完成
        await asyncio.gather(*tasks)

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

关键说明:

  • asyncio.Semaphore(5):括号里的数字就是你要限制的最大活跃请求数,比如改成10就允许同时跑10个请求。
  • async with semaphore::这个上下文管理器会自动帮你“拿许可”和“还许可”——当请求数达到上限时,新的任务会在这里等待,直到某个请求完成释放许可,才会继续执行。
  • 文件名的小坑:你原来的代码里固定写name.png,所有图片都会被覆盖成同一个文件,所以我改成了从URL提取文件名,你也可以用其他方式命名(比如给每个URL加索引)。

方法二:用TCPConnector限制全局连接数

如果你想限制整个ClientSession的所有连接数(不止是图片下载请求),可以用aiohttp.TCPConnector的limit参数:

import asyncio
import aiohttp

async def get_images(url, session):
    chunk_size = 100
    print(f'Making request to {url}')
    async with session.get(url=url) as r:
        filename = url.split('/')[-1]
        with open(f'path/{filename}', 'wb') as file:
            while True:
                chunk = await r.content.read(chunk_size)
                if not chunk:
                    break
                file.write(chunk)

async def main():
    # 创建连接器,限制最多5个连接
    connector = aiohttp.TCPConnector(limit=5)
    async with aiohttp.ClientSession(connector=connector) as session:
        image_urls = [
            'https://example.com/img1.png',
            'https://example.com/img2.png',
            # ...更多URL
        ]
        tasks = [get_images(url, session) for url in image_urls]
        await asyncio.gather(*tasks)

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

两种方法的区别:

  • Semaphore:只限制你指定的任务(比如这里的图片下载)的并发数,同一个session里的其他请求不受影响。
  • TCPConnector:限制整个session的所有连接数,不管是什么类型的请求,最多只能有limit个连接同时存在。

你可以根据自己的实际场景选,一般来说用Semaphore会更灵活哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:29:42