This rule raises when a TaskGroup or Nursery body contains only a single call to .start or .start_soon without passing
itself as a parameter.
TaskGroup and Nursery are powerful tools for structured concurrency that automatically manage the lifecycle of multiple concurrent tasks. However, when they are used to spawn only a single task that doesn’t need the nursery/TaskGroup instance itself, they add unnecessary overhead and complexity.
The main issues with using TaskGroup and Nursery for single tasks are:
Replace the TaskGroup with a direct function call when the TaskGroup body contains only a single create_task() call.
import asyncio
async def worker_task():
await asyncio.sleep(1)
async def main():
# Unnecessary TaskGroup for a single task
async with asyncio.TaskGroup() as tg:
tg.create_task(worker_task())
import asyncio
async def worker_task():
await asyncio.sleep(1)
async def main():
# Direct function call is simpler and more efficient
await worker_task()
Replace the nursery with a direct function call when the nursery body contains only a single start_soon() or start()
call.
import trio
async def worker_task():
await trio.sleep(1)
async def main():
# Unnecessary nursery for a single task
async with trio.open_nursery() as nursery:
nursery.start_soon(worker_task)
import trio
async def worker_task():
await trio.sleep(1)
async def main():
# Direct function call is simpler and more efficient
await worker_task()
Replace the task group with a direct function call when the task group body contains only a single start_soon() or
start() call.
import anyio
async def worker_task():
await anyio.sleep(1)
async def main():
# Unnecessary task group for a single task
async with anyio.create_task_group() as tg:
tg.start_soon(worker_task)
import anyio
async def worker_task():
await anyio.sleep(1)
async def main():
# Direct function call is simpler and more efficient
await worker_task()