Skip to content

asyncio-dangling-task (RUF006)

What it does

Checks for asyncio.create_task and asyncio.ensure_future calls that do not store a reference to the returned result.

Why is this bad?

Per the asyncio documentation, the event loop only retains a weak reference to tasks. If the task returned by asyncio.create_task and asyncio.ensure_future is not stored in a variable, or a collection, or otherwise referenced, it may be garbage collected at any time. This can lead to unexpected and inconsistent behavior, as your tasks may or may not run to completion.

Example

import asyncio

for i in range(10):
    # This creates a weak reference to the task, which may be garbage
    # collected at any time.
    asyncio.create_task(some_coro(param=i))

Use instead:

import asyncio

background_tasks = set()

for i in range(10):
    task = asyncio.create_task(some_coro(param=i))

    # Add task to the set. This creates a strong reference.
    background_tasks.add(task)

    # To prevent keeping references to finished tasks forever,
    # make each task remove its own reference from the set after
    # completion:
    task.add_done_callback(background_tasks.discard)

References