Python Threading Event

Summary: in this tutorial, you’ll learn how to use the Python threading Event object to communicate between threads.

Introduction to the Python threading Event object

Sometimes, you need to communicate between the threads. To do that, you can use a lock (mutex) and a boolean variable.

However, Python provides you with a better way to communicate between threads using the Event class from the threading module.

The Event class offers a simple but effective way to coordinate between threads: one thread signals an event while other threads wait for it.

The Event object wraps a boolean flag that can be set (True) or cleared (False). Multiple threads can wait for an Event to be set before proceeding or can reset the Event back to the cleared state.

The following illustrates the steps for using the Event object:

First, import the Event from the threading module:

from threading import EventCode language: Python (python)

Next, create a new Event object:

event = Event()Code language: Python (python)

By default, the event is not set (cleared). The is_set() method of the event object will return False:

if event.is_set():
   # ...Code language: Python (python)

Then, set an event using the set() method:

event.set()Code language: Python (python)

Once an event is set, all the threads that wait on the event will be notified automatically.

After that, unset an event via the clear() method:

event.clear()Code language: Python (python)

Finally, threads can wait for the event to be set via the wait() method:

event.wait()Code language: Python (python)

The wait() method blocks the execution of a thread until the event is set. In other words, the wait() method will block the current thread until another thread call the set() method to set the event.

If an event is set, the wait() function returns immediately.

To specify how long the thread is going to wait, you can use the timeout argument. For example:

event.wait(timeout=5) # wait for 5 secondsCode language: Python (python)

Python threading event example

The following example shows a simple example of using the Event object to communicate between threads:

from threading import Thread, Event
from time import sleep

def task(event: Event, id: int) -> None:
    print(f'Thread {id} started. Waiting for the signal....')
    event.wait()
    print(f'Received signal. The thread {id} was completed.')

def main() -> None:
    event = Event()

    t1 = Thread(target=task, args=(event,1))
    t2 = Thread(target=task, args=(event,2))

    t1.start()
    t2.start()

    print('Blocking the main thread for 3 seconds...')
    sleep(3) 
    event.set()



if __name__ == '__main__':
    main()Code language: Python (python)

Output:

Thread 1 started. Waiting for the signal....
Thread 2 started. Waiting for the signal....
Blocking the main thread for 3 seconds...
Received signal. The thread 1 was completed.
Received signal. The thread 2 was completed.Code language: Python (python)

How it works.

First, define the task() function that accepts an Event object and an integer:

def task(event: Event, id: int) -> None:
    print(f'Thread {id} started. Wait for the signal....')
    event.wait()
    print(f'Receive signal. The thread {id} was completed.')Code language: Python (python)

Inside, the task() function, we call the wait() method of the event object to wait for the event to be set by the main thread.

Second, create an Event object inside the main() function:

event = Event()Code language: Python (python)

Third, create two child threads that execute the task() function with the same event object and different id 1 and 2:

t1 = Thread(target=task, args=(event,1))
t2 = Thread(target=task, args=(event,2))Code language: Python (python)

Fourth, start both threads by calling the start() method:

t1.start()
t2.start()Code language: Python (python)

Fifth, call the sleep() method to block the main thread for three seconds:

sleep(3)Code language: Python (python)

Since the task() function call the wait() method of the event object, both t1 and t2 threads will wait for the event to be set before continuing.

Finally, set the event by calling the set() method from the main thread:

event.set()Code language: Python (python)

Both t1 and t2 threads will be notified and continue executing until the end.

Note that you’ll learn how to use the Event object to stop a child thread from the main thread in the next tutorial.

Practical example of using Threading event

The following example illustrates hwo to use the threading event to synchronize between two threads:

  • Thread #1 downloads a text file from URL https://www.ietf.org/rfc/rfc793.txt, once completed, it notifies the second thread to count the words from the downloaded text file.
  • Thread #2 starts and wait for the completed signal from the thread #1. Once, receiving the signal, it starts counting the words from the downloaded file.

Here’s the complete program:

from threading import Thread, Event
from urllib import request


def download_file(url, event):
    # Download the file form URL
    print(f"Downloading file from {url}...")
    filename, _ = request.urlretrieve(url, "rfc793.txt")

    # File download completed, set the event
    event.set()


def process_file(event):
    print("Waiting for the file to be downloaded...")
    event.wait()  # Wait for the event to be set

    # File has been downloaded, start processing it
    print("File download completed. Starting file processing...")

    # Count the number of words in the file
    word_count = 0
    with open("rfc793.txt", "r") as file:
        for line in file:
            words = line.split()
            word_count += len(words)

    # Print the word count
    print(f"Number of words in the file: {word_count}")


def main():
    # Create an Event object
    event = Event()

    # Create and start the file download thread
    download_thread = Thread(target=download_file, 
                             args=("https://www.ietf.org/rfc/rfc793.txt",  event))

    download_thread.start()

    # Create and start the file processing thread
    process_thread = Thread(target=process_file, args=(event,))
    process_thread.start()

    # Wait for both threads to complete
    download_thread.join()
    process_thread.join()

    print("Main thread finished.")

if __name__ == '__main__'    :
    main()
Code language: PHP (php)

Summary

  • Use the threading.Event class to communicate between threads.
  • Use the set() method to set the event and clear() method to unset the event.
  • Use the is_set() method to check if an event is set.
  • Use the wait() method to wait for the event to be set.
Did you find this tutorial helpful ?