Categories
General Python level 2 python

Python Asyncio Loops – A Beginner’s Guide

Recently, we covered the difference between Python’s asyncio.run() vs asyncio.loop.run_until_complete(). We learned that the asyncio.run() function is a high level wrapper around the low level run_until_complete() function. The asyncio.run() function abstracts out the creation, running, and closing of the event loop object used to execute the run_until_complete() function. What is the loop object from asyncio? We’ll find out in this post.

In this post we’ll cover:

  • A short introduction to asyncio Python
  • What is a Python asyncio event loop object?
    • Running an event loop
    • Scheduling callbacks
    • Creating futures, tasks, and coroutines
  • How can you use a Python asyncio loop?
  • When should you use an asyncio loop in Python?

What does Python asyncio do?

The asyncio Python library does exactly what you’d think based on the name. It handles asynchronous code execution. It introduces the ability to use the async/await keywords in a function definition. Using async functions allows us to await the execution of some code that isn’t I/O bound. In other words, execution of code that doesn’t need to be processed in the order that it’s written.

What is a Python asyncio event loop object?

Event loops are the core of every asyncio application. At a basic level, loops are the objects that run your async program. They “loop” through each of the asynchronous functions given to them. 

How can I use an asyncio loop object?

Loops are the objects that call your async program under the hood. To use a loop, you have to first get the loop object. The asyncio library has four ways to interact with loops. One, you can get the currently running event loop on the OS thread. Two, you can get an event loop that is not necessarily running. Three, you can assign an event loop to run on the current OS thread. Finally, four, you can create a new event loop. The respective function calls for these behaviors are get_running_loop(), get_event_loop(), set_event_loop(), and new_event_loop().

After getting the loop object, you can do a lot of things with it. Primarily: run the loop, schedule callbacks, create futures and tasks, work with network connections, create network servers, work with files, work with DNS, execute code in threads and pools, and run subprocesses. For the purpose of this beginner’s guide to asyncio loops, we’re going to focus on just a few of these tools. We’re going to focus on running loops, scheduling callbacks, and creating futures/tasks.

Run an asyncio Event Loop

This is the most basic function of event loops. You have to run them to use them. There are six basic functions you should know for running event loops.

  1. run_until_complete(<some Future object>) – this function runs a given Future object, usually a coroutine defined by the async/await pattern, until it’s complete. 
  2. run_forever() – this function runs the loop forever.
  3. stop() – the stop function stops a running loop.
  4. is_running() – this function checks if the event loop is currently running or not.
  5. is_closed() – this function checks if the event loop is closed or not.
  6. close() – the close function closes the event loop. The difference between close() and stop() is that callbacks will not be executed when close() is called, but they will be executed when stop() is called.

There are two more functions that you probably won’t need unless you’re developing more complex applications.

  1. shutdown_asyncgens() – used to close all currently open asynchronous generator functions.
  2. shutdown_default_executor() – used to close the default executor. This function waits for the threads to finish joining in the ThreadPoolExecutor first.

Schedule asyncio Callbacks

A callback is simply a function that’s meant to be executed at some point in the future. There are four functions for callbacks that you need to know.

  1. call_soon(<callback function>) – the call soon function schedules the passed in callback function to be executed on the next iteration of the event loop. This is not a threadsafe method.
  2. call_soon_threadsafe(<callback function>) –  this is the threadsafe version of the call soon function.
  3. call_later(delay, <callback function>) – this function schedules a callback function to be called after some amount of seconds. The delay parameter can be an integer or a float.
  4. call_when(when, <callback function>) – this function schedules a callback function to be called at the when time. The when time needs a timestamp in the same format as the loop.time() function. The time function returns a float based on the event loop’s internal clock.

Create Futures, Tasks, and Coroutines

Futures, tasks, and coroutines are almost the same thing. Coroutines are basically async/await functions. Tasks are Future-like objects that run coroutines in event loops. Future objects are simply awaitable functions. Futures are a generalized awaitable object. Tasks are specialized Future objects that execute coroutines. There are four functions you need to know for creating Futures, Tasks, and Coroutines.

  1. create_future() – this creates and attaches a asyncio.Future object to the event loop. This is the recommended way to create Future objects for event loops in asyncio.
  2. create_task(coroutine, name) –  this creates a Cask which schedules the execution of a Coroutine. The create task function returns a Task object. 
  3. set_task_factory(factory) – this creates a Task factory object which will be used by the create_task function. The factory method must have two parameters, a loop and Coroutine referring to the current loop and the desired Coroutine.
  4. get_task_factory(factory) – this returns the Task factory being used by the loop. If there’s no custom Task factory set, it returns None.

When should I use an asyncio loop?

The event loop object is runs loops for asynchronous execution of code in Python. You should use the asyncio event loop object when you need to run multiple functions that don’t rely on each other. You should not use the event loops if your functions’ inputs rely on the outputs of the other async functions.

Summary of a Beginner’s Guide to Python asyncio Loops

In this post we introduced the Python asyncio library and some of its’ basic functions. We learned that an event loop is the core structure for using the library. Event loops are asyncio objects that run Coroutines. Event loops are helpful when we’re running multiple functions that don’t rely on each other, but not when the functions do.

More by the Author

I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.