Home > Software engineering >  Is this a good alternative of asyncio.sleep
Is this a good alternative of asyncio.sleep

Time:07-30

I decided not use asyncio.sleep() and tried to create my own coroutine function as shown below. Since, time.sleep is an IO bound function, I thought this will print 7 seconds. But it prints 11 seconds.

import time
import asyncio


async def my_sleep(delay):
    time.sleep(delay)

async def main():
    start = time.time()
    await asyncio.gather(my_sleep(4), my_sleep(7))
    print("Took", time.time()-start, "seconds")

asyncio.run(main())

# Expected: Took 7 seconds
# Got: Took 11.011508464813232 seconds

Though if I write a similar code with threads, It does print 7 seconds. Do Task objects created by asyncio.gather not recognize time.sleep as an IO bound operation, the way threads do? Please explain why is it happening.

CodePudding user response:

time.sleep is blocking operation for event loop. It has no sense if you write async in defention of function because it not unlock the event loop (no await command)

This two questions might help you to understand more:

Python 3.7 - asyncio.sleep() and time.sleep()

Run blocking and unblocking tasks together with asyncio

CodePudding user response:

This would not work for you because time.sleep is a synchronous function.

From the 'perspective' of the event loop my_sleep might as well be doing a heavy computation within an async function, never yielding the execution context while working.

The first tell tale sign of this is that you're not using an await statement when calling time.sleep.

Making a synchronous function behave as an async one is not trivial, but the common approach is moving the function call to worker threads and awaiting the results. I'd recommend looking at the solution of anyio, they implemented a run_sync function which does exactly that.

  • Related