Joel Blum
Joel Blum

Reputation: 7878

Python Asyncio wait_for decorator

I am trying to write a decorator that calls asyncio.wait_for on the decorated function - the goal is to set a time limit on the decorated function. I expect the decorated function to stop running after time_limit but it does not. The decorator is being called fine but the code just sleeps for 30 seconds instead of being interrupted. Any ideas what I'm doing wrong?

def await_time_limit(time_limit):

    def Inner(func):
        async def wrapper(*args, **kwargs):
            return await asyncio.wait_for(func(*args, **kwargs), time_limit)
        return wrapper

    return Inner

@await_time_limit(5)
async def whatever 
    time.sleep(30) # this runs to the full 30 seconds and not stopped after 5
end

Upvotes: 1

Views: 383

Answers (1)

JayTurnr
JayTurnr

Reputation: 183

As we can see in this example here, the problem arises from using time.sleep not asyncio.sleep, since time.sleep will block the thread. You need to be careful not to have any blocking code

import asyncio
import time


def await_time_limit(time_limit):
    def Inner(func):
        async def wrapper(*args, **kwargs):
            return await asyncio.wait_for(func(*args, **kwargs), time_limit)
        return wrapper
    return Inner


@await_time_limit(5)
async def asleep():
    await asyncio.sleep(30) # this runs for only 5 seconds


@await_time_limit(5)
async def ssleep():
    time.sleep(30) # this runs to the full 30 seconds and not stopped after 5


t1 = time.time()
await asleep()
t2 = time.time()
print(t2-t1) # 5.018370866775513


t1 = time.time()
await ssleep()
t2 = time.time()
print(t2-t1) # 30.00193428993225

Upvotes: 2

Related Questions