Tuesday 26 January 2016

Raspberry Pi - Python Threading

Sometimes it would be useful to have two python programs running at the same time this is easy just start two separate programs. But what if the programs need to share information, then its a bit more tricky. Threading is a way to run two processes independently and they can share data.

Threading code

In the program definition you need to to import the treading module. I have also imported time to create delays. To use a variable in other functions or classes it must be defined as global, it is then initialised with value 0.0.

from threading import Thread
import time

global cycle
cycle = 0.0

To use treading a new class is created Hello5Program this will be run in a new program thread. The class has three definitions. The __init__ definition initialises the class setting running parameter to true. The terminate definition is used to exit the class. The run definition is where the main class code is written. The global variable cycle is defined here again linking it to the main programs global variable.  

class Hello5Program:  
    def __init__(self):
        self._running = True

    def terminate(self):  
        self._running = False  

    def run(self):
        global cycle
        while self._running:
            time.sleep(5) #Five second delay
            cycle = cycle + 1.0
            print "5 Second Thread cycle+1.0 - ", cycle

An instance of the class Hello5Program is created as FiveSecond then a thread FiveSecondThread is created containing this classes run definition. The thread is started. 

#Create Class
FiveSecond = Hello5Program()
#Create Thread
FiveSecondThread = Thread(target=FiveSecond.run)
#Start Thread
FiveSecondThread.start()

The rest of the main program has a loop increasing cycle by 0.1 and printing the result. When cycle is greater than 5 the program exits. As the program exits it must terminate the class by calling the terminate procedure. If the terminate procedure is not called the program will never exit.  

Exit = False #Exit flag
while Exit==False:
cycle = cycle + 0.1 
print "Main Program increases cycle+0.1 - ", cycle
time.sleep(1) #One second delay
if (cycle > 5): Exit = True #Exit Program

FiveSecond.terminate()
print "Goodbye :)"

Program result

The program output shows the increase of cycle by 0.1 then by 1.0 when the threaded runs both writing to the variable and printing the values. The thread finishes after the main program finishes because of the 5 second delay.
































Many threads can be created to do different functions. A thread can call any function in the main program. I have used threads to read sensors and digital inputs with the main program displaying the outputs to an LCD display. All this using Raspberry PI GPIO pins and Python threads.
It is also possible to run the same class as many threads if that is required.

Code example with two different threads

Here is the whole code with an extra thread

from threading import Thread
import time

global cycle
cycle = 0.0

class Hello5Program:  
    def __init__(self):
        self._running = True

    def terminate(self):  
        self._running = False  

    def run(self):
        global cycle
        while self._running:
            time.sleep(5) #Five second delay
            cycle = cycle + 1.0
            print "5 Second Thread cycle+1.0 - ", cycle

class Hello2Program:  
    def __init__(self):
        self._running = True

    def terminate(self):  
        self._running = False  

    def run(self):
        global cycle
        while self._running:
            time.sleep(2) #Five second delay
            cycle = cycle + 0.5
            print "5 Second Thread cycle+1.0 - ", cycle

#Create Class
FiveSecond = Hello5Program()
#Create Thread
FiveSecondThread = Thread(target=FiveSecond.run)
#Start Thread
FiveSecondThread.start()

#Create Class
TwoSecond = Hello2Program()
#Create Thread
TwoSecondThread = Thread(target=TwoSecond.run)
#Start Thread
TwoSecondThread.start()


Exit = False #Exit flag
while Exit==False:
cycle = cycle + 0.1 
print "Main Program increases cycle+0.1 - ", cycle
time.sleep(1) #One second delay
if (cycle > 5): Exit = True #Exit Program

TwoSecond.terminate()
FiveSecond.terminate()
print "Goodbye :)"

12 comments:

  1. Thank You so much for explaining it so well. Can you please share the code for the understated:
    "threads to read sensors and digital inputs with the main program displaying the outputs to an LCD display. All this using Raspberry PI GPIO pins and Python threads."

    ReplyDelete
  2. Thank you, your explaining so easy understand.

    ReplyDelete
  3. This tutorial has been extremely helpful, Thank You Very Much, Rob.

    This is exactly what I needed for my application- Which is to build a rover using Raspberry Pi and the threads would help me to distribute the workload keeping my Pi from the risk of falling to pieces due to workload.

    You Rock Rob.

    ReplyDelete
  4. Excellent Tutorial!

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete
  6. Very easy to underestand with your explenation. Thanks

    ReplyDelete
  7. Rob, great tutorial. I have a question: Is the sleep in each of the threads including the main program required to allow the other threads to execute? My application involves monitoring voltages, displaying it on the screen AND reporting over/under voltage events via email. My problem currently is that sending the email will freeze the program for up to 10 seconds while no updates can be done. If I push the email sending to a thread, will the main program retain execution to continue monitoring and not have to wait for the email send to complete?

    ReplyDelete
  8. Thanks so much. Really Appreciate it.

    ReplyDelete
  9. Finally threading is making sense. Thankyou

    ReplyDelete
  10. If I start the programm its mean:
    Traceback (most recent call last):
    File "/home/pi/PythonProjeke/youtube-dl.py", line 1, in
    import os, thearding
    ModuleNotFoundError: No module named 'thearding'

    Can you help me?

    ReplyDelete
  11. Awesome explanation and tutorial. I've 39 years of software development experience but I'm new to Pi, python and programing GPIOs (been coding business applications - accounting, payroll, etc). Bob you are gifted at imparting knowledge. You are one to follow.

    ReplyDelete
  12. Thank you Rob, I had a problem reading a PIR sensor in my program and the IRQ routine was too long to be reliable. I came across your page, and gave threading a try - first time....In an hour I had solved my problem thanks to your excellent explanation and example! Thank you very much! Steven in Canada

    ReplyDelete

Thank you fro reading my page.
Let me know if there is anything that I could add or change.
Please let me know if this information is helpful.