From:http://masnun.com/2015/11/20/python-asyncio-future-task-and-the-event-loop.htmlevent Loop
On any platform, when we want to do something asynchronously, it usually involves an event loop. An event loop is a loop this can register tasks to be executed, execute them, delay or even cancel them and handle Differe NT events related to these operations. Generally, we schedule multiple async functions to the event loop. The loop runs one function, while this function waits for IO, it pauses it and runs another. When the first function completes IO, it is resumed. Thus or more functions can co-operatively run together. This is the main goal of an event loop.
The event loop can also pass resource intensive functions to a thread pool for processing. The internals of the event loop is quite complex and we don ' t need to worry much about it right away. We just need to remember this event loop is the mechanism through which we can schedule our async functions and get th EM executed.
Futures/tasks
If you is into Javascript too, you probably know about Promise. In Python we have similar concepts–future/task. A supposed to has a result in the future. A Task is a subclass of the future that wraps a coroutine. When the coroutine finishes, the result of the Task is realized.
Coroutines
We discussed coroutines in the last blog post. It's A-pausing a function and returning a series of values periodically. A coroutine can pause the execution of the function by using the yield
yield from
or await
(python 3.5+) keywords in an express Ion. The function is paused until the yield
statement actually gets a value.
Fitting Event Loop and Future/task Together
It ' s simple. We need an event loop and we need to register our Future/task objects with the event loop. The loop would schedule and run them. We can add callbacks to our Future/task objects so, we can be notified if a future have it ' s results.
Very often we choose to use Coroutines We Wrap a coroutine in the future and get a Task object. When a coroutine yield
s, it is paused. When it had a value, it was resumed. When it return
S is, the Task has completed and gets a value. Any associated callback is run. If the Coroutine raises an exception, the Task fails and not resolved.
So let's move ahead and see example codes.
Python
1234567891011121314151617181920212223242526272829 |
import asyncio @Asyncio. Coroutine def slow_operation(): # Yield from suspends execution until # There ' s some result from Asyncio.sleep yield from asyncio. Sleep(1) # Our tasks are done, here's the result return ' future is done! ' def Got_result(future): Print(future. Result()) # Our Main Event looploop = asyncio. Get_event_loop() # We Create a task from a coroutinetask = loop. Create_task(slow_operation()) # notify US when the task was completetask. Add_done_callback(got_result) # The loop would close when the task has resolvedLoop. Run_until_complete(task) |
As can see already:
@asyncio.coroutine
Gets us the default event loop
loop.create_task(slow_operation())
Creates a task from the Coroutine returned byslow_operation()
task.add_done_callback(got_result)
Adds a callback to our task
loop.run_until_complete(task)
Runs the event loop until the task is realized. As soon as it has value, the loop terminates
The run_until_complete
function is a nice-to-manage the loop. Of course we could do this:
Python
123456789101112131415161718192021 |
import asyncio Async def slow_operation(): await Asyncio. Sleep(1) return ' future is done! ' def Got_result(future): Print(future. Result()) # We have the result, so let's stop loop. Stop() loop = asyncio. Get_event_loop() task = loop. Create_task(slow_operation()) task. Add_done_callback(got_result) # We Run ForeverLoop. Run_forever() |
Here we do the loop run forever and from our callback, we explicitly shut it is down when the future has resolved.
PYTHON Asyncio:future, TASK and the EVENT LOOP