@@ -414,6 +414,73 @@ reported by :meth:`asyncio.Task.cancelling`.
414
414
Improved handling of simultaneous internal and external cancellations
415
415
and correct preservation of cancellation counts.
416
416
417
+ Group Cancellation
418
+ ------------------
419
+
420
+ Cancelling an entire task group is not natively supported by the standard
421
+ library but can be achieved by adding a task to the group that raises an
422
+ exception and ignore that exception:
423
+
424
+ .. code-block :: python
425
+
426
+ import contextlib
427
+ from asyncio import TaskGroup
428
+
429
+ class CancelTaskGroup (Exception ):
430
+ """ Exception raised to cancel a task group."""
431
+
432
+ @contextlib.asynccontextmanager
433
+ async def CancellableTaskGroup ():
434
+ """ A cancellable task group."""
435
+ try :
436
+ async with TaskGroup() as group:
437
+ yield group
438
+ except * CancelTaskGroup:
439
+ print (' task group was cancelled' )
440
+
441
+ async def cancel_group (cancellable_task_group ):
442
+ """ Create a task that will cancel the group it belongs to."""
443
+ async def factory ():
444
+ raise CancelTaskGroup(cancellable_task_group)
445
+ await cancellable_task_group.create_task(factory())
446
+
447
+ The above helper functions can be used as follows:
448
+
449
+ .. code-block :: python
450
+
451
+ import asyncio
452
+
453
+ async def job (task_id , sleep_time , group = None ):
454
+ print (f " Task { task_id} : start " )
455
+ await asyncio.sleep(sleep_time)
456
+ if group is not None :
457
+ print (f " Task { task_id} : cancelling group " )
458
+ await cancel_group(group)
459
+ print (f " Task { task_id} : done " )
460
+
461
+ async def main ():
462
+ async with CancellableTaskGroup() as group:
463
+ # task 1 is cancelled before being done
464
+ group.create_task(job(1 , 2 , None ))
465
+ # task 2 is responsible for cancelling the entire group
466
+ group.create_task(job(2 , 1 , group))
467
+ # task 3 completes normally
468
+ group.create_task(job(3 , 0 , None ))
469
+
470
+ asyncio.run(main())
471
+
472
+ Expected output (note that "Task 2: done" is not printed since task 2 is
473
+ itself cancelled before completion):
474
+
475
+ .. code-block :: text
476
+
477
+ Task 1: start
478
+ Task 2: start
479
+ Task 3: start
480
+ Task 3: done
481
+ Task 2: cancelling group
482
+ task group was cancelled
483
+
417
484
Sleeping
418
485
========
419
486
0 commit comments