asyncio.gather cancellation behaviour
Stephan Houben
stephanh42 at gmail.com.invalid
Fri Sep 8 11:10:15 EDT 2017
Hi all,
I am a bit mystified about the rationale of the cancellation
behaviour of asyncio.gather.
Case 1:
"If the outer Future is cancelled, all children (that have not completed
yet) are also cancelled."
Case 2:
"If any child is cancelled, this is treated as if it raised
CancelledError – the outer Future is not cancelled in this case.
(THIS IS TO PREVENT THE CANCELLATION OF ONE CHILD TO CAUSE OTHER CHILDREN TO
BE CANCELLED.)" [capitalization mine]
Indeed I can observe this behavior. However, I would like to further
understand the reasoning for not cancelling in case 2.
Outside asyncio.gather, cancelling an "outer future" does NOT cancel
the "inner future" on which the outer future is currently await-ing, while
cancelling the "inner future" will raise a CancelledError which will
cancel the outer future.
Example:
import asyncio
f1 = asyncio.Future()
async def make_f2():
await f1
f2 = asyncio.ensure_future(make_f2())
f2.cancel() # cancelling f1 instead will cancel BOTH f1 and f2
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(f2)
except asyncio.CancelledError:
print("got CancelledError")
print("f1 cancelled: ", f1.cancelled()) # prints False
print("f2 cancelled: ", f2.cancelled()) # prints True
So cancellation "normally" proceeds from inner future -> outer future.
It seems somebody worked hard to reverse the direction in case of
asyncio.gather. Why?
Stephan
More information about the Python-list
mailing list