Introduction: How to Create a Thread in Python Using Threading.thread() Module and Pass Data Arguments to Thread

Raspberry Pi, a small and affordable single-board computer, has gained immense popularity for its versatility and ease of use. It is widely used for building home automation system, robots and network attached devices. Python is a powerful programming language widely used for developing applications on the desktop and Raspberry Pi platform

In this tutorial we will learn How to create a thread using Python 3.x and pass data to and from the thread using various methods.

Python being Cross platform (Desktop PC' to Raspberry Pi) ,the tutorial will teach the user to create multithreaded applications on a wide variety of platforms including Raspberry Pi

Tutorial is written to be applicable for both Desktop computers and embedded system computers like Raspberry Pi.

When you want to monitor a lot of IO from multiple sensors or network traffic on a raspberry Pi it makes sense to run these IO operations on separate threads to improve responsiveness.

You can have a sensors inputting data from wide variety of sensors like temperature ,pressure, humidity which are uploaded to the cloud through the network port. In such cases, it makes sense to run the two operations on separate Python threads to improve responsiveness


You can find the original Tutorial along with Source code below.



Supplies

  1. Raspberry Pi /Desktop Computer
  2. Python Interpreter
  3. Text Editor

Step 1: What Are Threads and How Are They Used in Python

Threads are the smallest unit of execution within a process. They enable concurrent execution of tasks within a single process, allowing multiple operations to be performed simultaneously or in a parallel-like manner.

In Python, threading works differently compared to languages like Java, C#, or Go, where threads can execute concurrently on multicore processors. Due to limitations in the design of the Python interpreter (CPython), only one thread can run at a time.

Python threads are handy for speeding up operations that are I/O bound, which is great for both desktop and Raspberry Pi programmers. Whether you're writing desktop applications or tinkering with Raspberry Pi projects, threading can help with tasks like writing to a file, downloading data from the web, or reading from sensors and devices.

Moreover, the threading library can also boost the responsiveness of graphical user interfaces (GUIs) on both platforms. By offloading lengthy tasks to separate threads, you can ensure that your GUI remains smooth and responsive, enhancing the user experience.

However, it's worth noting that Python threading won't provide significant speed-ups for CPU-bound operations, like complex calculations that tie up the processor. In such cases, both desktop and Raspberry Pi programmers should consider utilizing the Multiprocessing module to take advantage of multiple CPU cores for improved performance


Step 2: Creating a Thread in Python Using Threading Module

Creating a thread in Python is straightforward, thanks to the built-in threading module. Here's a basic example of how to create a thread


import threading     #import the threading module

def do_something():
   #some statements here
   pass

t1 = threading.Thread(target = do_something) #create the thread t1
t1.start()


  1. First We import the threading module.
  2. then We define a function do_something(): that will be executed in the thread. It doesnt do anything now.Aplass holder pass is placed
  3. We create a Thread object called t1, specifying the target parameter as the function to be executed in the thread.
  4. We start the thread by calling the start() method on the t1 object.

This is a basic example, and you can create more complex threads by passing arguments to the target function or subclassing the Thread class and overriding its run() method.



Step 3: How to Use Thread.join() in Python Threading

In Python threading, the join() method is used to wait for a thread to complete its execution before proceeding with the main program. Here's how to use join() in Python threading:

import time
import threading  #required for threading 

def do_something():
  print(f'\nEntered do_something() ')

  time.sleep(2)

  print('\nDone Sleeping in Thread\n')


print(f'\nStart of Main Thread ')

t1 = threading.Thread(target = do_something)  #create the thread t1
t1.start() 
t1.join()                  #start the threads


print('\nEnd of Main Thread\n+---------------------------+')
  1. We define a function do_something() that prints " Entered do_something()"
  2. We create a Thread object called t1, specifying the target parameter as the do_something() function.
  3. We start the thread by calling the start() method on the t1 object.
  4. We call the join() method on the t1 object. This causes the main program to wait until t1 completes its execution.
  5. After t1 finishes execution, the main program proceeds to print the message "End of Main Thread\n+---------------------------+'"
  6. Using join() ensures that the main program doesn't proceed until the thread has completed its task, allowing for synchronization between the main thread and the child thread.

Step 4: Program to Show the Use of .join() Function in Python Threading

Let me outline a hypothetical scenario where join() is essential. Imagine a program tasked with downloading three webpages from the internet and merging them into a single page.


Here's how it could work:


Firstly, we can create three separate threads, each responsible for downloading one webpage. These threads would operate concurrently, fetching data at varying speeds based on network conditions.


Meanwhile, the main thread will wait until all three threads have completed their downloads. We achieve this by calling the join() method on each thread within the main thread.


Once all downloads are complete, the collected data is passed to a function called create_single_webpage(), which merges the downloaded content into a single webpage.


Without utilizing join(), the main thread would rush ahead and attempt to execute create_single_webpage() before all downloads are finished, likely resulting in errors or incomplete data integration.


In summary, join() ensures proper synchronization, allowing the main thread to coordinate and wait for the completion of all concurrent tasks before proceeding with subsequent operations.

Step 5: How to Pass Arguments to Python Threads

import time
import threading

def do_something(myarg1):
  print(myarg1)
  time.sleep(2)

# Creating a thread and passing a single argument
t1 = threading.Thread(target=do_something, args=(1,))  

# Starting the thread
t1.start()  
t1.join()

# Explanation
# In this code, we pass a single argument to the function do_something() using the args parameter of the threading.Thread() function. 
# Here, we're passing the integer 1 to the do_something() function.
# Remember to add a comma after the argument (1) when using args.

# You can also pass multiple arguments to your function.

def do_something(myarg1, myarg2, myarg3):
  print(myarg1, myarg2, myarg3)
  time.sleep(2)

# Creating a thread and passing multiple arguments
t2 = threading.Thread(target=do_something, args=(1, 2, 3)) 


In the provided code, arguments are passed to Python threads using the args parameter when creating a Thread object. Let's break it down:


Defining the Target Function:

def do_something(myarg1):
  print(myarg1)
  time.sleep(2)

Here, do_something() is the function that will be executed by the thread.

It takes one argument, myarg1, which will be printed by the function.


Creating a Thread:

t1 = threading.Thread(target=do_something, args=(1,))
threading.Thread() is used to create a new thread.

The target parameter specifies the function to be executed in the thread, which is do_something.

The args parameter is a tuple containing the arguments to be passed to the target function. In this case, it's (1,), passing the integer 1 as the argument to do_something.


Starting the Thread:

t1.start()

The start() method is called on the thread object t1 to start its execution.

By providing the arguments (1,) to the args parameter when creating the thread t1, we effectively pass the value 1 as the argument to the do_something() function when it is executed by the thread.

This is a common pattern for passing arguments to Python threads. You can pass multiple arguments by including them in the tuple passed to args. For example:


t2 = threading.Thread(target=do_something_else, args=(arg1, arg2, arg3))

Here, do_something_else() is a function expecting three arguments, and arg1, arg2, and arg3 are the values to be passed to it when executed by the thread t2.