首页 > 解决方案 > 是否有类似于使用上下文管理器的 Pythonic 方式在后台运行异步任务?

问题描述

最近我想在运行其他任务的同时在后台运行一些异步任务,但我认为代码不够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?

标签: pythonasync-awaitpython-asynciocontextmanager

解决方案


这样的东西已经存在了吗?

目前还没有,但这是一个非常有用的想法。该概念的更通用版本将添加到Python 3.8中,这是未来的 Python 版本,其形式为受CurioTrioTaskGroup中现有技术启发的类。

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

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

如果不是,这是否被认为比现有方式更 Pythonic 或更少 Pythonic?

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


推荐阅读