是否有类似于使用上下文管理器的 Pythonic 方法在后台执行 运行 异步任务?

Is there a Pythonic way to run async task in background similar to using a contextmanager?

最近我想 运行 在后台执行一些异步任务,同时 运行 执行其他任务,但我认为代码不是 Pythonic够了:

task = asyncio.create_task(long_task())
await short_task()
await task

所以我把它做得更Pythonic:

@asynccontextmanager
async def run_in_background(coro):
    task = asyncio.create_task(coro)
    yield task
    await task


async def main():
    async with run_in_background(long_task()):
        await short_task()

这样的东西已经存在了吗?如果不是,这是否被认为比现有方式更 Pythonic 或更少 Pythonic?

Does something like this already exist?

目前还没有,但这是一个非常有用的想法。该概念的更通用版本将以 TaskGroup class inspired by prior art in Curio and Trio.[=17= 的形式添加到 Python 3.8 未来的 Python 版本中]

我建议增强实现以使用 finally,以保证即使出现异常也会等待后台任务;例如:

@asynccontextmanager
async def run_in_background(coro):
    task = asyncio.create_task(coro)
    try:
        yield task
    finally:
        await task

If not is this considered more Pythonic or less Pythonic than the existing way?

问题的这一部分显然是基于意见的,但我会说上下文管理器更 Pythonic 因为它 确保 后台任务已完成并在块离开时等待。它还确保后台任务中的异常do not pass silently,这是异步代码中错误的常见来源。

trio 提供了一种更好的方法来处理苗圃对象:

async with trio.open_nursery() as nursery:
    nursery.start_soon(long_task())  # Task will run in background

    await short_task()
    # Wait for background tasks to finish