Skip to content

Linting issues for asyncio #771

Open
@cclauss

Description

@cclauss

I have little expertise in using asyncio. Are any of these problematic?

% ruff check --select=ASYNC,RUF006 --statistics

16	RUF006  	asyncio-dangling-task
 3	ASYNC110	async-busy-wait
 2	ASYNC230	blocking-open-call-in-async-function
 1	ASYNC251	blocking-sleep-in-async-function
Found 22 errors.

% ruff rule RUF006 # https://docs.astral.sh/ruff/rules/asyncio-dangling-task

asyncio-dangling-task (RUF006)

Derived from the Ruff-specific rules linter.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions