关闭使用 asyncio.ensure_future 启动的子任务

Closing subtasks launched with asyncio.ensure_future

如果我有以下情况:

async def foo():
    for i in range(10):
        print "1"
        await asyncio.sleep(1)

async def bar()
    t = asyncio.ensure_future(foo())
    while not t.done():
        print("waiting")
        await asyncio.sleep(0.5)

async def baz():
    t = asyncio.ensure_future(bar())
    await asyncio.sleep(2.5)
    t.cancel()

并且 baz() 在一个更大的事件循环中被调用,我如何确保 foo() 被取消?

A try/finally 块将捕获 CancelledError 异常:

task = asyncio.ensure_future(foo())
try:
    [...]
finally:
    task.cancel()  # return False if task is already finished

一些task functions已经处理了子任务的取消:

result = await asyncio.wait_for(foo(), 60.)  
result, = await asyncio.gather(foo())

在这两个示例中,foo() 都包含在任务中,如果要取消父任务,则会自动取消。


编辑

这是一个协程控制另一个协程执行的简单示例:

async def control(coro, timeout=1.):
    task = asyncio.ensure_future(coro)
    while not task.done():
        try:
            print("The task is not finished yet")
            await asyncio.wait([task, asyncio.sleep(timeout)], "FIRST_COMPLETED")
        except asyncio.CancelledError:
            task.cancel()
    return task.result()  # Raise task.exception() if any

现在,await control(foo(), 1.) 应该像 await foo() 一样工作(关于取消、异常和结果)除了它每秒打印 The task is not finished yet 直到 foo() 完成。