5.1 Event Loop
Let's quickly touch upon the second part of asynchronicity that's everywhere: the Event Loop, Task, and Future.
Picture the Event Loop as an orchestra conductor, Task as the musicians, and Future as the sheet music the musicians have to play. The conductor (Event Loop) coordinates the work of the musicians (Task) who perform the music (asynchronous operations), reading the sheet music (Future).
The Event Loop is the core of asynchronous programming in Python. It handles executing asynchronous tasks, managing events, and processing I/O operations. The Event Loop continuously checks for new events or tasks and runs them as they become ready.
Main functions
-
run_forever(): Starts the Event Loop and keeps it running untilstop()is called. -
run_until_complete(future): Starts the Event Loop and stops it when the given Future or coroutine finishes. stop(): Stops the Event Loop.-
create_task(coroutine): Schedules the execution of a coroutine as a task.
Example usage:
import asyncio
async def hello():
print("Hello, world!")
await asyncio.sleep(1)
print("Hello again!")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()
In this example, first, we use the get_event_loop() method to get the current EventLoop object from the asyncio library.
Then we add the hello coroutine to this EventLoop and ask it to execute it using the run_until_complete() method.
In the final step, we close the EventLoop using the close() method.
When you run this code, you'll first see "Hello, world!", then the program will wait for 1 second, and after that, it'll print "Hello again!". This demonstrates how the Event Loop manages the execution of an asynchronous function.
We'll take a closer look at these actions in the next lecture.
5.2 Tasks
Tasks are a wrapper for coroutines, allowing you to manage their execution and monitor their state. Tasks enable you to run coroutines concurrently, managing them through the Event Loop.
Creating and managing tasks
-
asyncio.create_task(coroutine): Creates a task to run a coroutine. -
Task.result(): Returns the result of a completed task or raises an exception if the task finished with an error. Task.cancel(): Cancels the execution of a task.
Example usage:
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello")
async def main():
task = asyncio.create_task(say_hello())
await task
asyncio.run(main())
In this example, we wrap the say_hello() coroutine in a Task object. It's also an asynchronous object, so to get its result, you need to use the await operator.
When you run this code, the program will wait 1 second and then print "Hello". This demonstrates how Task manages the execution of a coroutine and how we can wait for its completion using await.
We'll talk more about working with Task in the next lecture.
5.3 Futures
Future objects represent the result of an asynchronous operation that will be available in the future. They allow you to manage the state of an asynchronous operation by setting a result or an exception.
Main methods:
-
set_result(result): Sets the result for theFutureobject. -
set_exception(exception): Sets an exception for theFutureobject. -
result(): Returns the result of theFutureobject or raises an exception if the operation completed with an error. -
exception(): Returns the exception if it was set.
Example usage:
import asyncio
async def set_future(fut, value):
await asyncio.sleep(1)
fut.set_result(value)
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
await set_future(fut, 'Hello, future!')
print(fut.result())
asyncio.run(main())
In this example, we create a Future, set its value after a second, and then print the result. You'll see that the program waits for a second before printing 'Hello, future!'. This demonstrates how a Future represents a result that will become available in the future.
Unlike a Task object, a Future object is tied to a specific Event Loop, and the executing asynchronous function can write its result to it. Although it usually works a bit differently.
Most often, Future objects are used in conjunction with Task objects, which provide higher-level management of asynchronous operations.
Now that you're familiar with the Event Loop, Task, and Future, we'll look at them more closely.
GO TO FULL VERSION