程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

Run Python coroutine functions concurrently, but start additional coroutines as soon as particular coroutines have completed

发布于2024-12-12 11:01     阅读(985)     评论(0)     点赞(19)     收藏(1)


I have four total coroutines (async def functions): A, B, C, and D. C can't be called until I know the result of A, and D can't be called until I know the result of A and B. See the attached diagram. I want to run these coroutines concurrently such that the total time spent until I get the results from C and D is minimized. task dependency graph

We should start by running A and B concurrently, but I it would be sub-optimal to use a, b = asyncio.gather(get_a(), get_b()) because C should be started as soon as A finishes, and doesn't need to wait around for B to complete.

Similarly, we could run A and C in sequence, while also running B concurrently (as shown below) but in this case we might be waiting around to start D longer than needed if A and B have completed but C is still running:

async def group_1():
    a = await get_a()
    c = await get_c(a)
    return c

c, b = asyncio.gather(
    group_1(),
    get_b(),
)

How can I execute these tasks without any unnecessary waiting?

I imagine I could use callbacks if necessary, but I would prefer to use a higher level construct if possible. Additionally, my actual use case has more tasks than this with more complex dependency chains, and I think callbacks would quickly become difficult to reason about.


解决方案


OP here. I think I've come up with a solution for this problem, which is to use asyncio.create_task() to start A and B in the background. C and D can then both await the A task (full example below). I'm still not certain if this is the cleanest way to do it though, so additional answers are still welcome.

import asyncio
async def get_a():
    await asyncio.sleep(1)
    return "a"

async def get_b():
    await asyncio.sleep(1)
    return "b"
    
async def get_c(a):
    await asyncio.sleep(1)
    return "c"
    
async def get_d(a, b):
    await asyncio.sleep(1)
    return "d"

async def main():
    a_task = asyncio.create_task(get_a())
    b_task = asyncio.create_task(get_b())
    
    async def c_wrapper():
        a = await a_task
        return await get_c(a)
    
    async def d_wrapper():
        a = await a_task
        b = await b_task
        return await get_d(a, b)
    
    return await asyncio.gather(c_wrapper(), d_wrapper())

asyncio.run(main())


所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:https://www.pythonheidong.com/blog/article/2046454/cea8b280300f2a36fbc1/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

19 0
收藏该文
已收藏

评论内容:(最多支持255个字符)