General Python

Python Asyncio Loops – A Beginner’s Guide

Recently, we covered the difference between Python’s vs asyncio.loop.run_until_complete(). We learned that the function is a high level wrapper around the low level run_until_complete() function. The 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:

What does Python



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




    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




    is that callbacks will not be executed when


    is called, but they will be executed when


    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



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


    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


    time. The


    time needs a timestamp in the same format as the


    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


    object to the event loop. This is the recommended way to create Future objects for event loops in



  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


    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



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

Learn More

To learn more, feel free to reach out to me @yujian_tang on Twitter, connect with me on LinkedIn, and join our Discord. Remember to follow the blog to stay updated with cool Python projects and ways to level up your Software and Python skills! If you liked this article, please Tweet it, share it on LinkedIn, or tell your friends!

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.

Yujian Tang

Yujian Tang

I started my professional software career interning for IBM in high school after winning ACSL two years in a row. I got into AI/ML in college where I published a first author paper to IEEE Big Data. After college I worked on the AutoML infrastructure at Amazon before leaving to work in startups. I believe I create the highest quality software content so that’s what I’m doing now. Drop a comment to let me know!

Connect with me on LinkedIn!

Make a one-time donation

Your contribution is appreciated.


Make a monthly donation

Your contribution is appreciated.

Donate monthly

Make a yearly donation

Your contribution is appreciated.

Donate yearly