I'm reading 'Fluent Python' by 'Luciano Ramalho' over and over, but I couldn't understand asyncio.sleep's behavior inside asyncio.
Book says at one part:
Never use time.sleep in asyncio coroutines unless you want to block the main thread, therefore freezing the event loop and probably the whole application as well. (...) it should yield from asyncio.sleep(DELAY).
On the other part:
Every Blocking I/O function in the Python standard library releases the GIL (...) The time.sleep() function also releases the GIL.
As time.sleep() releases GIL codes on other thread can run, but blocks current thread. Since asyncio is single-threaded, I understand that time.sleep blocks asyncio loop.
But, how asyncio.sleep() isn't blocking thread? Is it possible to not delay event loop and wait at the same time?
解决方案
You can test how both behave with this small example and see how asyncio.sleep(1) doesn't actually give you any clue on how long it will "sleep" because it's not what it really does:
import asyncio
import time
from datetime import datetime
async def sleep_demo():
print("sleep_demo start: ", datetime.now().time())
await asyncio.sleep(1)
print("sleep_demo end: ", datetime.now().time())
async def I_block_everyone():
print("I_block_everyone start: ", datetime.now().time())
time.sleep(3)
print("I_block_everyone end: ", datetime.now().time())
asyncio.gather(*[sleep_demo(), I_block_everyone()])
This prints:
sleep_demo start: 04:46:55.902913
I_block_everyone start: 04:46:55.903119
I_block_everyone end: 04:46:58.905383
sleep_demo end: 04:46:58.906038
The blocking call time.sleep prevent the event loop from scheduling the future that resumes sleep_demo. In the end, it gains control back only after approximately 3 seconds.
Now concerning "The time.sleep() function also releases the GIL.", this is not a contradiction as it will only allow another thread to execute (but the current thread will remain pending for x seconds). Somewhat both look a bit similar, in one case the GIL is released to make room for another thread, in asyncio.sleep, the event loop gains control back to schedule another task.