并发URL使用python获取循环

时间:2018-02-13 13:09:15

标签: python multithreading python-asyncio gevent curio

我需要运行大约500个并发循环。每个循环将按顺序获取分页的REST端点,直到它到达500个端点中每个端点的最后一页。其中一些循环只有5到10页,所以它会快速完成,但其他循环有100页。

问题在于我需要将此URL提取到顺序阻塞循环中,因为由于API限制,必须按顺序提取每个页面(API将抛出错误如果我获取第7页,则第5页获取)。因此,这里的并行单元是每个循环,而不是每个URL在循环内获取。

在任何地方都没有进行繁重的计算。只需获取一个页面,然后将原始内容放入kafka主题中。除了依赖于许多核心的多进程之外,我对任何建议持开放态度。 AsyncIO,Gevent,多线程......

修改1:

实际问题是,如果我使用 aiohttp 异步获取每个循环内的每个页面,我无法保证在第1页之后将获取第2页。请求将被启动以正确的顺序,但绝对不能保证请求将以正确的顺序到达并在端点处理。

编辑2:

正如user4815162342 aiohttp所指出的那样

谢谢!

1 个答案:

答案 0 :(得分:1)

在asyncio中,您可以并行启动与端点一样多的循环,并等待所有循环完成。每个循环将使用aiohttp按顺序获取端点页面。例如:

async def download_loop(session, endpoint):
    for i in itertools.count(1):
        try:
            async with session.get(endpoint, params={'page': str(i)}) as resp:
                content = await resp.read()
        except aiohttp.ClientResponseError:
            break   # no more pages
        # do something with the response content

async def download(endpoints):
    loop = asyncio.get_event_loop()
    async with aiohttp.ClientSession() as session:
        # Start all loops in parallel and wait for them to finish.
        # This will start as many loops as there are endpoints.
        await asyncio.wait([download_loop(session, endpoint)
                            for endpoint in endpoints])

# for testing:
loop = asyncio.get_event_loop()
loop.run_until_complete(download(['http://endpoint1', 'http://endpoint2', ...]))

生产代码可能还会捕获aiohttp.ClientConnectionError并重新尝试该网址。