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.