From 06dd589ae3aa846eb65aedcf796f94aa9bffb220 Mon Sep 17 00:00:00 2001 From: why-not-try-calmer Date: Tue, 25 Oct 2022 15:59:28 +0200 Subject: [PATCH 1/2] Added some clarificatory comments. The purpose of the comments is to rule out the implication that asyncio.TaskGroup is a drop-in replacement / better alternative to asyncio.gather(). Both have their idiomatic uses cases, and asyncio.gather() works well for tasks that do not schedule tasks themselves, especially when the caller needs to consume their result as soon as possible. --- Doc/library/asyncio-task.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index fb6d23fda03e41..886b559c9d5cd2 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -248,8 +248,9 @@ Creating Tasks .. note:: - :meth:`asyncio.TaskGroup.create_task` is a newer alternative - that allows for convenient waiting for a group of related tasks. + :meth:`asyncio.TaskGroup.create_task` is a new alternative + based on `structural concurrency principles `_ + that allows for waiting for a group of related tasks with strong safety guarantees. .. important:: @@ -328,7 +329,7 @@ Example:: async with asyncio.TaskGroup() as tg: task1 = tg.create_task(some_coro(...)) task2 = tg.create_task(another_coro(...)) - print("Both tasks have completed now.") + print(f"Both tasks have completed now: {task1.result()}, {task2.result()}") The ``async with`` statement will wait for all tasks in the group to finish. While waiting, new tasks may still be added to the group @@ -447,8 +448,11 @@ Running Tasks Concurrently Tasks/Futures to be cancelled. .. note:: - A more modern way to create and run tasks concurrently and - wait for their completion is :class:`asyncio.TaskGroup`. + A new alternative to create and run tasks concurrently and + wait for their completion is :class:`asyncio.TaskGroup`. While *TaskGroup* + provides strong safety guarantees for scheduling a nesting of subtasks, *gather* comes in handy + for tasks that do not schedule subtasks and need to have their results consumed eagerly + (i.e. when destructuring the result(s) into a tuple). .. _asyncio_example_gather: From 65ea4530bd9ed0f4bca6fb25ef91f667aec796f3 Mon Sep 17 00:00:00 2001 From: why-not-try-calmer Date: Tue, 25 Oct 2022 22:17:59 +0200 Subject: [PATCH 2/2] Addressing comments and taking onboard suggestions from reviewer. --- Doc/library/asyncio-task.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 886b559c9d5cd2..ddc49b768ca8c8 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -249,7 +249,7 @@ Creating Tasks .. note:: :meth:`asyncio.TaskGroup.create_task` is a new alternative - based on `structural concurrency principles `_ + based on `structural concurrency principles `_ that allows for waiting for a group of related tasks with strong safety guarantees. .. important:: @@ -449,10 +449,14 @@ Running Tasks Concurrently .. note:: A new alternative to create and run tasks concurrently and - wait for their completion is :class:`asyncio.TaskGroup`. While *TaskGroup* - provides strong safety guarantees for scheduling a nesting of subtasks, *gather* comes in handy - for tasks that do not schedule subtasks and need to have their results consumed eagerly - (i.e. when destructuring the result(s) into a tuple). + wait for their completion is :class:`asyncio.TaskGroup`. *TaskGroup* + provides stronger safety guarantees than *gather* for scheduling a nesting of subtasks. + That is, if a task (or a subtask, a task scheduled by a task) + raises an exception, *TaskGroup* will, while *gather* will not, + cancel the remaining scheduled tasks). However the terser *gather* might be + preferred for *Iterable* of tasks which individually handle their own exceptions, or more + generally, when having some tasks survive the cancellation + of others is an acceptable outcome. .. _asyncio_example_gather: