Suppose a small Python application fetches measurements and weights concurrently, then combines them into one score. One fetch raises an exception while the other is still running. Before comparing how languages spell concurrent work, which lifecycle should this calculation require?
I would first decide whether a failed fetch makes the whole calculation unusable. With asyncio.TaskGroup, a member failure other than CancelledError causes the remaining members to be cancelled, and the group waits for its tasks before finishing its exit. Calling a coroutine function alone does not schedule that work. The fetches need to become tasks in the group.
Next comes a different readiness decision. If both tasks return normally but the weights are unsuitable, collection has completed without establishing that calculation should begin. Should the application reject those inputs, request replacements, or produce a partial result? TaskGroup does not choose that policy.
I would also check what caller cancellation should do and whether fetch cleanup preserves cancellation by propagating CancelledError. Swallowing it can disrupt the group's cancellation behavior.
For this particular application, I would choose TaskGroup if either fetch failing should end the combined request and the scope must wait for its members. Then I would validate the returned data before calculating. Those requirements give a language comparison something concrete to preserve.
