Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what does `yield from asyncio.sleep(delay)` do?

The following example from Python in a Nutshell sets x to 23 after a delay of a second and a half:

@asyncio.coroutine
def delayed_result(delay, result):
  yield from asyncio.sleep(delay)
  return result

loop = asyncio.get_event_loop()
x = loop.run_until_complete(delayed_result(1.5, 23))

I feel difficult to understand what yield from asyncio.sleep(delay) does.

From https://docs.python.org/3/library/asyncio-task.html#asyncio.sleep

Coroutine asyncio.sleep(delay, result=None, *, loop=None)

Create a coroutine that completes after a given time (in seconds). If result is provided, it is produced to the caller when the coroutine completes.

So asyncio.sleep(delay) returns a coroutine object.

What does a coroutine object "completes" mean?

What values does yield from asyncio.sleep(delay) provide to the main program?

Thanks.

like image 295
Tim Avatar asked Sep 13 '17 22:09

Tim


1 Answers

The following line of code :

time.sleep(5)

...freezes the execution of your code for 5 seconds. Nothing further is computed or executed until the sleep function has completed it's 5 second nap as the application can't proceed without the sleep function returning control to the caller. This is called synchronous programming, when there is no mechanism for the application to change its focus and complete other tasks in periods of waiting such as waiting for the results of a call to a database, a web api or as in this case the sleep function. In synchronous programming there is no need for an event loop as there is no expectation that the application manages its time nor that it switches tasks for efficiency gains.

The following code :

asyncio.sleep(5)

... is part of the asyncio library, designed for asynchronous programming where an event loop is assigned tasks to be competed and it (the event loop) monitors the state of all its tasks and switches from one to another with the objective of minimising the amount of time idle/waiting. This is not threading where multiple processes are being executed simultaneously, this is merely optimising task execution so the CPU is not left idle, therefore gaining hugely reduced overall execution times.

The yield from keyword (python 3.5 onwards await keyword can be used) is the moment where the event loop has the chance to leave one task to finish (e.g. While a query is returned from a database call) and focus on another task which the event loop is aware of and can actually be computed/executed in the meantime.

@asyncio.coroutine decorator + yield from is compatible with python 3.5 onwards but using the new keyword async def to define an asyncronous coroutine and the await keyword within it to allow the event loop to evaluate switching to another task is the common and future proof way to go if you're 3.5 or above.

Asyncronous python can be quite difficult to get your head round but there are a number of excellent pycon talks on the subject from the previous few years - look for one on Youtube and if course read the docs😇

like image 86
user3535074 Avatar answered Sep 18 '22 20:09

user3535074