Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

superfastpython.com

How to Use an Asyncio Event in Python -


Super Fast Python

Jason Brownlee
10–12 minutes

Last Updated on November 14, 2023

It is common to need to share a variable between concurrent tasks that may be


set and checked.
Asyncio provides a concurrency primitive that provides exactly this called an
event via the asyncio.Event class. It is essentially a mutex lock and a boolean
variable, but also offers the ability for a calling coroutine to wait for the event to
be set, a capability not provided by a simple mutex.
In this tutorial, you will discover how to use an event concurrency primitive
in asyncio.
After completing this tutorial, you will know:
What is an event concurrency primitive and why we cannot just use a boolean
variable.
How to use asyncio event shared between coroutines and tasks.
How an asyncio event might be used to trigger behavior across multiple
concurrent tasks.
Let’s get started.
What is an Asyncio Event
How to Use an Asyncio Event
Example of an Asyncio Event
Further Reading
Takeaways

What is an Asyncio Event


An event provides a way to notify coroutines that something has happened.
This is achieved using a coroutine-safe manner that avoids race conditions.
An asyncio event can be used to notify multiple asyncio tasks that some event
has happened.
— Asyncio Synchronization Primitives
An event manages an internal boolean flag that can be either set or not set.
Coroutines can check the status of the event, change the status of the event or
wait on the event for it to be set.
Python provides events for other units of concurrency, such as threads via the

1 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

threading.Event class:
Threading Event Object In Python
It also provides an event for notifying processes via the multiprocessing.Event
class:
Multiprocessing Event Object In Python
The asyncio.Event provides similar functionality for use with coroutines,
instead of threads or processes. Importantly, the asyncio.Event is not thread-
safe, i.e. only coroutine-safe.
An event object. Not thread-safe.
— Asyncio Synchronization Primitives
Now that we know what an event is, let’s look at how we might use it in an
asyncio program.
An event is a simple concurrency primitive that allows communication between
coroutines.
An asyncio.Event object wraps a boolean variable that can either be “set”
(True) or “not set” (False).
Coroutines sharing the event instance can check if the event is set, set the
event, clear the event (make it not set), or wait for the event to be set.
The asyncio.Event provides an easy way to share a boolean variable between
coroutines that can act as a trigger for an action.
An Event object manages an internal flag that can be set to true with the set()
method and reset to false with the clear() method. The wait() method blocks
until the flag is set to true. The flag is set to false initially.
— Asyncio Synchronization Primitives
First, an event object must be created and the event will be in the “not set”
state.

...
# create an instance of an event
event = asyncio.Event()

Once created we can check if the event has been set via the is_set() function
which will return True if the event is set, or False otherwise.
For example:

...
# check if the event is set
if event.is_set():
# do something...

The event can be set via the set() function. Any coroutines waiting on the event
to be set will be notified.
For example:

...
# set the event
event.set()

2 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

The event can be marked as “not set” (whether it is currently set or not) via the
clear() function.

...
# mark the event as not set
event.clear()

Finally, coroutines can wait for the event to be set via the wait() function.
Calling this function will block until the event is marked as set (e.g. another
coroutine calling the set() function). If the event is already set, the wait()
function will return immediately.

...
# wait for the event to be set
await event.wait()

Now that we know how to use an asyncio.Event, let’s look at a worked


example.

Example of an Asyncio Event


We can explore how to use an asyncio.Event object.
In this example, we will create a suite of coroutines that each will perform some
processing and report a message. All coroutines will use an event to wait to be
set before starting their work. The main coroutine will set the event and trigger
the processing in all coroutines.
First, we can define a task coroutine that takes the shared asyncio.Event
instance and a unique integer to identify the task.

# task coroutine
async def task(event, number):
# ...

Next, the function will wait for the event to be set before starting the processing
work.

...
# wait for the event to be set
await event.wait()

Once triggered, the task will generate a random number, block for a moment
and report a message.

...
# generate a random value between 0 and 1
value = random()
# block for a moment
await asyncio.sleep(value)
# report a message
print(f'Task {number} got {value}')

3 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

Tying this together, the complete task coroutine is listed below.

# task coroutine
async def task(event, number):
# wait for the event to be set
await event.wait()
# generate a random value between 0 and 1
value = random()
# block for a moment
await asyncio.sleep(value)
# report a message
print(f'Task {number} got {value}')

The main coroutine will first create the shared asyncio.Event instance, which
will be in the “not set” state by default.

...
# create a shared event object
event = asyncio.Event()

Next, we can create and start five new coroutines specifying the task()
coroutine with the event object and a unique integer as arguments.

...
# create and run the tasks
tasks = [asyncio.create_task(task(event, i)) for i in range(5)]

Finally, the main coroutine will block for a moment, then trigger the processing
in all of the coroutines via the event object.

...
print('Main blocking...')
await asyncio.sleep(0)
# start processing in all tasks
print('Main setting the event')
event.set()

Finally, the main coroutine will block and wait for all tasks to complete via the
asyncio.wait() function.

...
# await for all tasks to terminate
_ = await asyncio.wait(tasks)

You can learn more about the asyncio.wait() function in the tutorial:
How to Use Asyncio wait() in Python
Tying this all together, the complete example is listed below.

4 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

1 # SuperFastPython.com
2 # example of using an asyncio event object
3 from random import random
4 import asyncio
5 # task coroutine
6 async def task(event, number):
7 # wait for the event to be set
8 await event.wait()
9 # generate a random value between 0 and 1
10 value = random()
11 # block for a moment
12 await asyncio.sleep(value)
13 # report a message
14 print(f'Task {number} got {value}')
15 # main coroutine
16 async def main():
17 # create a shared event object
18 event = asyncio.Event()
19 # create and run the tasks
20 tasks = [asyncio.create_task(task(event, i)) for i in range(5)]
21 # allow the tasks to start
22 print('Main blocking...')
23 await asyncio.sleep(0)
24 # start processing in all tasks
25 print('Main setting the event')
26 event.set()
27 # await for all tasks to terminate
28 _ = await asyncio.wait(tasks)
29 # run the asyncio program
30 asyncio.run(main())
31
32
33

Running the example first creates the main() coroutine and uses it as the entry
point into the asyncio program.
The main() coroutine runs and creates and schedules five task coroutines.
It then sleeps, suspending and allowing the tasks to run and start waiting on
the event.
The main coroutine resumes, reports a message then sets the event to True. It
then blocks and waits for all issued tasks to complete.

5 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

This triggers all five coroutines. They resume in turn perform their processing
and report a message.
Note, results will vary each time the program is run given the use of random
numbers.
This highlights how coroutines can wait for an event to be set and how we can
notify coroutines using an event.

Main blocking...
Main setting the event
Task 3 got 0.36705703414223256
Task 1 got 0.4852630342496812
Task 0 got 0.7251916806567016
Task 4 got 0.8104350284043036
Task 2 got 0.9726611709531982

Free Python Asyncio Course


Download your FREE Asyncio PDF cheat sheet and get BONUS access to my
free 7-day crash course on the Asyncio API.
Discover how to use the Python asyncio module including how to define,
create, and run new coroutines and how to use non-blocking I/O.
Learn more

Further Reading
This section provides additional resources that you may find helpful.
Python Asyncio Books
Python Asyncio Jump-Start, Jason Brownlee. (my book!)
Python Asyncio Interview Questions, Jason Brownlee.
Asyncio Module API Cheat Sheet
I also recommend the following books:
Python Concurrency with asyncio, Matthew Fowler, 2022.
Using Asyncio in Python, Caleb Hattingh, 2020.
asyncio Recipes, Mohamed Mustapha Tahrioui, 2019.
Guides
Python Asyncio: The Complete Guide
Python Asynchronous Programming
APIs
asyncio — Asynchronous I/O
Asyncio Coroutines and Tasks
Asyncio Streams
Asyncio Subprocesses
Asyncio Queues

6 of 7 11/25/2023, 6:09 PM
How to Use an Asyncio Event in Python - Super Fast Python about:reader?url=https%3A%2F%2Fsuperfastpython.com%2Fasyncio...

Asyncio Synchronization Primitives


References
Asynchronous I/O, Wikipedia.
Coroutine, Wikipedia.

Takeaways
You now know how to use an asyncio event in Python.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Oli Woodman on Unsplash

7 of 7 11/25/2023, 6:09 PM

You might also like