This rule raises an issue when a synchronous time.sleep() call is used within an asynchronous function.

Why is this an issue?

Synchronous functions like time.sleep() halt the execution of the current thread. In an asynchronous context, which relies on a single-threaded event loop to manage multiple tasks concurrently, calling time.sleep() blocks this entire event loop. When the event loop is blocked, it cannot switch between tasks, process I/O events, or respond to other operations. Consequently, all other concurrent asynchronous tasks are paused until the time.sleep() call completes. This effectively negates the benefits of using async/await by turning a non-blocking operation (waiting) into a blocking one that freezes the application’s concurrency model.

For instance, if an asynchronous web server uses time.sleep() in a request handler, it won’t be able to process any other incoming requests until the sleep call completes, leading to poor performance and responsiveness.

The correct approach in asynchronous programming is to use non-blocking sleep functions provided by the specific asynchronous framework being used (e.g., asyncio, Trio, AnyIO). These functions give control back to the event loop, allowing it to run other tasks while the current task is "sleeping".

How to fix it in Asyncio

Code examples

Noncompliant code example

import time
import asyncio

async def sleeping_function():
    time.sleep(1) # Noncompliant

asyncio.run(sleeping_function())

Compliant solution

import asyncio

async def sleeping_function():
    await asyncio.sleep(1)

asyncio.run(sleeping_function())

How to fix it in Trio

Code examples

Noncompliant code example

import time
import trio

async def sleeping_function():
    time.sleep(1) # Noncompliant

trio.run(sleeping_function)

Compliant solution

import trio

async def sleeping_function():
    await trio.sleep(1)

trio.run(sleeping_function)

How to fix it in AnyIO

Code examples

Noncompliant code example

import time
import anyio

async def sleeping_function():
    time.sleep(1) # Noncompliant

anyio.run(sleeping_function)

Compliant solution

import anyio

async def sleeping_function():
    await anyio.sleep(1)

anyio.run(sleeping_function)

Resources

Documentation