@@ -414,6 +414,53 @@ 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 |
+Terminating a Task Group |
|
418 |
+------------------------ |
|
419 |
+ |
|
420 |
+While terminating a task group is not natively supported by the standard |
|
421 |
+library, termination can be achieved by adding an exception-raising task |
|
422 |
+to the task group and ignoring the raised exception: |
|
423 |
+ |
|
424 |
+.. code-block:: python |
|
425 |
+ |
|
426 |
+ import asyncio |
|
427 |
+ from asyncio import TaskGroup |
|
428 |
+ |
|
429 |
+ class TerminateTaskGroup(Exception): |
|
430 |
+ """Exception raised to terminate a task group.""" |
|
431 |
+ |
|
432 |
+ async def force_terminate_task_group(): |
|
433 |
+ """Used to force termination of a task group.""" |
|
434 |
+ raise TerminateTaskGroup() |
|
435 |
+ |
|
436 |
+ async def job(task_id, sleep_time): |
|
437 |
+ print(f'Task {task_id}: start') |
|
438 |
+ await asyncio.sleep(sleep_time) |
|
439 |
+ print(f'Task {task_id}: done') |
|
440 |
+ |
|
441 |
+ async def main(): |
|
442 |
+ try: |
|
443 |
+ async with TaskGroup() as group: |
|
444 |
+ # spawn some tasks |
|
445 |
+ group.create_task(job(1, 0.5)) |
|
446 |
+ group.create_task(job(2, 1.5)) |
|
447 |
+ # sleep for 1 second |
|
448 |
+ await asyncio.sleep(1) |
|
449 |
+ # add an exception-raising task to force the group to terminate |
|
450 |
+ group.create_task(force_terminate_task_group()) |
|
451 |
+ except* TerminateTaskGroup: |
|
452 |
+ pass |
|
453 |
+ |
|
454 |
+ asyncio.run(main()) |
|
455 |
+ |
|
456 |
+Expected output: |
|
457 |
+ |
|
458 |
+.. code-block:: text |
|
459 |
+ |
|
460 |
+ Task 1: start |
|
461 |
+ Task 2: start |
|
462 |
+ Task 1: done |
|
463 |
+ |
417 |
464 |
Sleeping |
418 |
465 |
======== |
419 |
466 |
|