How to create a new thread in Python

Welcome to the world of multi-threading in Python! In this tutorial we will explore how to create a new thread for your Python program.


What is a Thread?

To fully understand threading, you need to have some basic Computer Hardware knowledge.

Modern Computers have more than just a single execution unit (also called a CPU core), and can thus execute multiple tasks at the same time (also known as parallelism).

A CPU core is an actual physical computation unit, built into the Processor. Modern Processor’s have around 4 – 16 CPU cores.

Normally every program executes on a single thread, or in simpler terms, a single CPU core. Multithreading allows us to allocate a program more than one thread, taking advantage of the multiple cores a CPU has to offer. Heavy computational tasks can split up across multiple threads, significantly improving performance.


Creating a Thread in Python

Here is the syntax for creating a new thread in Python using the threading library.

thread = threading.Thread(target = function, args=(argument,))

In the above code, we are using the Thread class from the threading module, which takes two parameters. The first parameter is the name of the function that we want the thread to execute.

Once the thread is created, we need to call the start() method on it before it actually begins executing.

Let’s try and code a simple example using threads.

Here we have used the logging library to provide us with some useful output information along with it’s time stamps. This will help us understand threads better.

from threading import Thread
from time import sleep
import logging

format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")

def func():
    logging.info("Thread starting")
    sleep(2)
    logging.info("Thread finishing")

thread = Thread(target = func)
thread.start()

logging.info("Main function executing")

thread.join()

The thread that we create in the above example executes the func() function. This function contains two logging statements, between which it waits two seconds. However, while this thread is “waiting” the main thread can continue execution.

17:52:54: Thread starting
17:52:54: Main function executing
17:52:56: Thread finishing

As you can see from the above image, the Main thread logs a statement to the console while the other thread is waiting. This is the concept of parallelism.

A slight problem that can occur is that the main thread might finish execution and shut down before the child thread. In order to prevent this from happening, we need to make the main thread wait for all the child threads to finish. To do this we use the join() method (shown in the above code example too).

thread.join()

The main thread will pause it’s execution when it sees a join() function until the repsective thread if finished. You can also use these at mid-way points in your program if you need the child threads to finish before the main thread continues with a certain task.


There are certain scenarios in which using threads becomes a necessity. For example if the main thread is currently waiting for input from the console, then this pauses execution until the user has finished entering the data. If you need to be executing some other task(s) while waiting for input, you can create a new thread.


Passing an argument to a Thread

Let’s take a look at another example using threads. This time we will be using a function that accepts some parameters. This example is also a more realistic scenario in which threads might be used.

We have three arrays in the below example which need to be sorted. To speed this process up, we can create a new thread for each array and sort it there using the bubblesort() function.

from threading import Thread
from time import sleep
import logging

format = "%(asctime)s.%(msecs)03d: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")

def bubbleSort(arr, n): 
    for i in range(n-1): 
        for j in range(0, n-i-1): 
            if arr[j] > arr[j+1]: 
                arr[j], arr[j+1] = arr[j+1], arr[j]
    logging.info(arr)

arrays = [[3,6,1,2,8,4,6,4,1,8,0,3,7,2,6],
          [8,5,2,3,0,7,1,5,9,2,6,5,2,7,8],
          [7,3,8,6,9,3,4,0,2,3,4,7,8,5,2]]

threads = []
for i in range(3):
    threads.append(Thread(target=bubbleSort, 
                          args=(arrays[i], len(arrays[i]),)))
    threads[i].start()

logging.info("Main function executing")

for index, thread in enumerate(threads):
    logging.info(f"Thread {index+1} is finished")
    threads[index].join()

Here you can notice from the timestamp that all three threads finished sorting the arrays at the same time.

18:35:59.761: [0, 1, 1, 2, 2, 3, 3, 4, 4, 6, 6, 6, 7, 8, 8]
18:35:59.761: [0, 1, 2, 2, 2, 3, 5, 5, 5, 6, 7, 7, 8, 8, 9]
18:35:59.761: [0, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9]
18:35:59.761: Main function executing
18:35:59.763: Thread 1 is finished
18:35:59.763: Thread 2 is finished
18:35:59.764: Thread 3 is finished

Note: Remember to include the little comma after the last argument in the Thread() Class! That’s not a typo, it’s meant to be there.

If you want to further improve this example, randomly generate arrays of large sizer (1000+ elements) and then try to sort them both with threads, and without and then compare the speed difference.


This marks the end of the How to create a new thread in Python Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments