Tom*_*auz 6 python contextmanager async-await python-asyncio
最近想在后台运行一些异步任务,同时运行其他任务,但我认为代码不够Pythonic:
task = asyncio.create_task(long_task())
await short_task()
await task
Run Code Online (Sandbox Code Playgroud)
所以我让它更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()
Run Code Online (Sandbox Code Playgroud)
像这样的东西已经存在了吗?如果不是,这是否被认为比现有方式更 Pythonic 或更少 Pythonic?
这样的东西已经存在了吗?
目前还没有,但这是一个非常有用的想法。该概念的更通用版本将添加到Python 3.8(未来的 Python 版本)中,其形式是受Curio和TrioTaskGroup中现有技术启发的类。
我建议增强 use 的实现finally,保证即使在出现异常的情况下也会等待后台任务;例如:
@asynccontextmanager
async def run_in_background(coro):
task = asyncio.create_task(coro)
try:
yield task
finally:
await task
Run Code Online (Sandbox Code Playgroud)
如果不是,这是否被认为比现有方式更Pythonic 或更少Pythonic?
问题的这一部分显然是基于意见的,但我想说上下文管理器更Pythonic,因为它确保后台任务已完成并在块离开时等待。它还确保后台任务中的异常不会静默地传递,这是 asyncio 代码中错误的常见来源。
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
Run Code Online (Sandbox Code Playgroud)