If I have the following:
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()
And baz() is called in a larger event loop, how can I make sure that foo() is cancelled?
A try/finally block would catch the CancelledError exception:
task = asyncio.ensure_future(foo())
try:
[...]
finally:
task.cancel() # return False if task is already finished
Some task functions already handle the cancellation of subtasks:
result = await asyncio.wait_for(foo(), 60.)
result, = await asyncio.gather(foo())
In both examples, foo() is wrapped in a task and would be canceled automatically if the parent task were to be canceled.
EDIT
Here's a simple example of a coroutine controlling the execution of another one:
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
Now, await control(foo(), 1.) should work exactly like await foo() (regarding cancellation, exception and result) except it prints The task is not finished yet every second until foo() is done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With