Last Updated on September 12, 2022
You can use an Event Object in Python via the threading.Event class.
In this tutorial you will discover how to use an event object in Python.
Let’s get started.
Need for an Event Object
A thread is a thread of execution in a computer program.
Every Python program has at least one thread of execution called the main thread. Both processes and threads are created and managed by the underlying operating system.
Sometimes we may need to create additional threads in our program in order to execute code concurrently.
Python provides the ability to create and manage new threads via the threading module and the threading.Thread class.
You can learn more about Python threads in the guude:
In concurrent programming in threads, sometimes we need to coordinate threads with a boolean variable. This might be to trigger an action or signal some result.
This could be achieved with a mutual exclusion lock (mutex) and a boolean variable, but provides no way for threads to wait for the variable to be set True.
Instead, this can be achieved using an event object.
What is an event object and how can we use it in Python?
Run loops using all CPUs, download your FREE book to learn how.
How to Use an Event Object
Python provides an event object via the threading.Event class.
An event is a simple concurrency primitive that allows communication between threads.
A threading.Event object wraps a boolean variable that can either be “set” (True) or “not set” (False). Threads 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 threading.Event provides an easy way to share a boolean variable between threads that can act as a trigger for an action.
This is one of the simplest mechanisms for communication between threads: one thread signals an event and other threads wait for it.
— Event Objects, threading — Thread-based parallelism
First, an event object must be created and the event will be in the “not set” state.
1 2 3 |
... # create an instance of an event event = threading.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:
1 2 3 4 |
... # check if the event is set if event.is_set(): # do something... |
The event can be set via the set() function. Any threads waiting on the event to be set will be notified.
For example:
1 2 3 |
... # set the event event.set() |
The event can be marked as “not set” (whether it is currently set or not) via the clear() function.
1 2 3 |
... # mark the event as not set event.clear() |
Finally, threads can wait for the event to set via the wait() function. Calling this function will block until the event is marked as set (e.g. another thread calling the set() function). If the event is already set, the wait() function will return immediately.
1 2 3 |
... # wait for the event to be set event.wait() |
From reviewing the source code for threading.Event, waiting threads are only notified when the set() function is called, not when the clear() function is called.
A “timeout” argument can be passed to the wait() function which will limit how long a thread is willing to wait in seconds for the event to be marked as set.
The wait() function will return True if the event was set while waiting, otherwise a value of False returned indicates that the event was not set and the call timed-out.
1 2 3 |
... # wait for the event to be set with a timeout event.wait(timeout=10) |
Now that we know how to use a threading.Event, let’s look at a worked example.
Example of Using an Event Object
We can explore how to use a threading.Event object.
In this example we will create a suite of threads that each will perform some processing and report a message. All threads will use an event to wait to be set before starting their work. The main thread will set the event and trigger the processing in all threads.
First, we can define a target task function that takes the shared threading.Event instance and a unique integer to identify the thread.
1 2 3 |
# target task function def task(event, number): # ... |
Next, the function will wait for the event to be set before starting the processing work.
1 2 3 |
... # wait for the event to be set event.wait() |
Once triggered, the thread will generate a random number, block for a moment and report a message.
1 2 3 4 5 |
... # begin processing value = random() sleep(value) print(f'Thread {number} got {value}') |
Tying this together, the complete target task function is listed below.
1 2 3 4 5 6 7 8 |
# target task function def task(event, number): # wait for the event to be set event.wait() # begin processing value = random() sleep(value) print(f'Thread {number} got {value}') |
The main thread will first create the shared threading.Event instance, which will be in the “not set” state by default.
1 2 3 |
... # create a shared event object event = Event() |
Next, we can start five new threads specifying the target task() function with the event object and a unique integer as arguments.
1 2 3 4 5 |
... # create a suite of threads for i in range(5): thread = Thread(target=task, args=(event, i)) thread.start() |
Finally, the main thread will block for a moment, then trigger the processing in all of the threads via the event object.
1 2 3 4 5 6 |
... # block for a moment print('Main thread blocking...') sleep(2) # start processing in all threads event.set() |
Tying this all together, the complete example is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# SuperFastPython.com # example of using an event object from time import sleep from random import random from threading import Thread from threading import Event # target task function def task(event, number): # wait for the event to be set event.wait() # begin processing value = random() sleep(value) print(f'Thread {number} got {value}') # create a shared event object event = Event() # create a suite of threads for i in range(5): thread = Thread(target=task, args=(event, i)) thread.start() # block for a moment print('Main thread blocking...') sleep(2) # start processing in all threads event.set() # wait for all the threads to finish... |
Running the example first creates and starts five threads. Each thread waits on the event before it starts processing.
The main thread blocks for a moment, allowing all threads to get started and start waiting on the event. The main thread then sets the event. This triggers all five threads that perform their processing and report a message.
Note, your specific results will differ given the use of random numbers.
1 2 3 4 5 6 |
Main thread blocking... Thread 2 got 0.12310258010408259 Thread 4 got 0.2951602689055347 Thread 3 got 0.2995528547475702 Thread 0 got 0.6661975710559368 Thread 1 got 0.6687449622581129 |
Free Python Threading Course
Download your FREE threading PDF cheat sheet and get BONUS access to my free 7-day crash course on the threading API.
Discover how to use the Python threading module including how to create and start new threads and how to use a mutex locks and semaphores
Further Reading
This section provides additional resources that you may find helpful.
Python Threading Books
- Python Threading Jump-Start, Jason Brownlee (my book!)
- Threading API Interview Questions
- Threading Module API Cheat Sheet
I also recommend specific chapters in the following books:
- Python Cookbook, David Beazley and Brian Jones, 2013.
- See: Chapter 12: Concurrency
- Effective Python, Brett Slatkin, 2019.
- See: Chapter 7: Concurrency and Parallelism
- Python in a Nutshell, Alex Martelli, et al., 2017.
- See: Chapter: 14: Threads and Processes
Guides
- Python Threading: The Complete Guide
- Python ThreadPoolExecutor: The Complete Guide
- Python ThreadPool: The Complete Guide
APIs
References
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Takeaways
You now know how to use a threading.Event Object in Python
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Harley-Davidson on Unsplash
Do you have any questions?