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

时间:2016-01-27 04:07:41

标签: python python-asyncio

如果我有以下内容:

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()?

1 个答案:

答案 0 :(得分:2)

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()