首页 > 解决方案 > 使用 Python 3.7+ 进行 100k API 调用,使用 asyncio 并行进行 100

问题描述

使用 asyncio async/await 和 Python 3.7+ 交付 100k API 调用的最佳方法是什么?这个想法是始终并行使用 100 个任务?

应该避免的是:
1. 开始处理所有 100k 任务
2. 等待所有 100 个并行任务完成,以便安排新的 100 个批次。

这个例子说明了第一种方法,这不是我们所需要的。

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
            'http://python.org',
            'https://google.com',
            'http://yifei.me'
        ]
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            tasks.append(fetch(session, url))
        htmls = await asyncio.gather(*tasks)
        for html in htmls:
            print(html[:100])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

标签: pythonpython-asynciopython-3.7

解决方案


使用semaphore. 信号量用于限制并发操作。Python 的 asyncio 带有自己的异步信号量版本。

import aiohttp
import asyncio

async def fetch(session, url, sema):
    async with sema, session.get(url) as response:
        return await response.text()

async def main():
    urls = [
            'http://python.org',
            'https://google.com',
            'http://yifei.me',
            'other urls...'
        ]
    tasks = []
    sema = asyncio.BoundedSemaphore(value=100)
    async with aiohttp.ClientSession() as session:
        for url in urls:
            tasks.append(fetch(session, url, sema))
        htmls = await asyncio.gather(*tasks)
        for html in htmls:
            print(html[:100])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

推荐阅读