Python协程中的并行异步IO

2024-05-12 22:42:23 发布

您现在位置:Python中文网/ 问答频道 /正文

简单的例子:我需要并行地发出两个不相关的HTTP请求。最简单的方法是什么?我希望是这样的:

async def do_the_job():
    with aiohttp.ClientSession() as session:
        coro_1 = session.get('http://httpbin.org/get')
        coro_2 = session.get('http://httpbin.org/ip')
        return combine_responses(await coro_1, await coro_2)

换句话说,我想启动IO操作并等待它们的结果,以便它们有效地并行运行。这可以通过asyncio.gather实现:

async def do_the_job():
    with aiohttp.ClientSession() as session:
        coro_1 = session.get('http://example.com/get')
        coro_2 = session.get('http://example.org/tp')
        return combine_responses(*(await asyncio.gather(coro_1, coro_2)))

接下来,我想有一些复杂的依赖结构。我希望在具备所有先决条件时启动操作,并在需要结果时获得结果。这里帮助asyncio.ensure_future将单独的任务与单独由事件循环管理的协同路由分开:

async def do_the_job():
    with aiohttp.ClientSession() as session:
        fut_1 = asyncio.ensure_future(session.get('http://httpbin.org/ip'))
        coro_2 = session.get('http://httpbin.org/get')
        coro_3 = session.post('http://httpbin.org/post', data=(await coro_2)
        coro_3_result = await coro_3
        return combine_responses(await fut_1, coro_3_result)

为了在逻辑流中使用协程实现并行的非阻塞IO,我必须使用asyncio.ensure_futureasyncio.gather(它实际上使用asyncio.ensure_future)?有没有一种不那么“冗长”的方式?

通常开发人员必须考虑哪些协程应该成为单独的任务并使用上述函数来获得最佳性能,这是真的吗?

在事件循环中使用没有多个任务的协同路由有意义吗?

在现实生活中,事件循环任务有多“重”?当然,它们比操作系统线程或进程“轻”。我应该在多大程度上尽可能减少此类任务的数量?


Tags: theorgasynciohttpgetasyncsessiondef