【问题标题】:Chain asyncio coroutines inline in asyncio.gather在 asyncio.gather 中内联链式异步协程
【发布时间】:2020-02-23 20:54:23
【问题描述】:

我有一个假设的asyncio.gather 场景:

await asyncio.gather(
    cor1,
    [cor2, cor3],
    cor4,
)

我想在这里按顺序执行cor2cor3。除了像这样定义外部协程之外,是否还有一些捷径:

async def cor2_cor3():
    await cor2
    await cor3

await asyncio.gather(
    cor1,
    cor2_cor3,
    cor4,
)

有没有更简洁的快捷方式?

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    有没有更简洁的快捷方式?

    asyncio 没有提供开箱即用的功能。如果 asyncio 任务有一个等效于 JavaScript 的 Promise.then 的方法,你就可以使用 asyncio.create_task(cor2()).then(cor3())。但是等价的 asyncio add_done_callback 是一个更底层的构造,它只是设置回调而不创建新的未来,这使得链接不方便。

    要按顺序执行协程,您需要编写一个简单的实用程序函数,例如(未经测试):

    async def chain(*aws):
        ret = None
        for aw in aws:
            ret = await aw
        return ret
    

    然后你可以调用gather为:

    await asyncio.gather(cor1(), chain(cor2(), cor3()), cor4())
    

    【讨论】:

    • 您提出的链函数存在问题,因为它只会返回链式协程的最后一个结果。理想情况下,它应该返回所有协程的结果,然后它们也应该在asyncio.gather 中手动解包。尽管如此,这确实回答了我的问题,而且您所描述的方法似乎是这里最好的方法。
    • @Granitosaurus 好点,幸运的是,将结果收集到列表中并返回它是微不足道的。这表明“链”的含义并不明确 - 基于cor2_cor3 示例,我假设您根本不关心结果,或者您只想要最后一个协程的结果。此外,“链接”可能意味着将一个协程的结果作为参数传递给下一个协程。我怀疑语义歧义是 stdlib 中省略 chain 的部分原因,另一部分是当你确实需要它时它很容易实现。
    猜你喜欢
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多