Neinstein
Neinstein

Reputation: 1033

Threading does not thread in my Python code

First of all, I learned Python on my own from online tutorials and (mostly) learning by doing, so I might did some strange things in my code. :) So, I am working om my first bigger project with Raspberry Pi, and for that I need codes running parallel. I wrote this part of my code for managing a simple D-pad:

Problematic code

import threading
import time
import pigpio


# input from the D-pad goes to these pins
BUTT_UP = 12
BUTT_LEFT = 16
BUTT_CENTER = 25
BUTT_RIGHT = 20
BUTT_DOWN = 21


class dpad_monitoring(threading.Thread):
    '''thread for monitoring the D-Pad'''

    def __init__(self, thread_ID, butt_up, butt_left, butt_center, butt_right, butt_down, res = 10.00):

        threading.Thread.__init__(self)
        self.running = True
        self.thread_ID = thread_ID

        # number of checks per sec
        self.res = res

        # key pins
        self._pins = [butt_up, butt_left, butt_center, butt_right, butt_down]

        #key monitor
        self.last_pressed = 0

        '''key numbers:
         UP      LEFT    CENTER     RIGHT     DOWN
          1       2        3          4         5       '''

        # setting up GPIO
        self.pi = pigpio.pi()
        for i in range(0, len(self._pins)):
            self.pi.set_mode(self._pins[i], pigpio.INPUT)
            self.pi.set_pull_up_down(self._pins[i], pigpio.PUD_UP)

    def stop(self):
        '''stopping the thread cleanly'''
        self.pi.stop()
        self.running = False

    def run(self):
        '''checks which button is pressed as many times per sec as specified 
            in the res variable in init. If any of them is pressed, it suspends itself
            until self.last_pressed is set to 0 again by main()'''


        while self.running:

            states = []
            for i in range(0, len(self._pins)):
                state = not self.pi.read(self._pins[i])  # pi.read returns 1L if the pin is high, 
                states.append(state)                #   what means the button is not pressed, 0L when pressed

            for i in range(0, len(states)):
                if states[i]:
                    self.last_pressed = i+1

            '''UGLY AS SHIT but works now, will change to locks after the code works'''
            if self.last_pressed != 0 :
                while self.last_pressed != 0:
                    pass
            else:
                time.sleep(1/self.res)


            print 'im groot'  # for debugging



def main():

    print 'ok' #debug

    dpad = dpad_monitoring(0, BUTT_UP, BUTT_LEFT, BUTT_CENTER, BUTT_RIGHT, BUTT_DOWN)
    dpad.run()

    print 'okey' #debug again 

    while i != 3:

        i = dpad.last_pressed
        if i == 1:
            print 'UP'
            dpad.last_pressed = 0
        if i == 2:
            print 'LEFT'
            dpad.last_pressed = 0
        if i == 4:
            print 'RIGHT'
            dpad.last_pressed = 0
        if i == 5:
            print 'DOWN'
            dpad.last_pressed = 0

    print 'CENTER, stopping'
    time.sleep(0.5)
    dpad.stop()

if __name__ == '__main__':
    main()

The problem is when I run the code, I get this:

ok
im groot
im groot
im groot
im groot
im groot
im groot

... (endless groot)

So it seems the code gets stuck at dpad.run(). Now AFAIK, the main point of threading is that the code continues after calling the run() function and can interact with the threading object, so I don't know what the he'll is going on. Could you, all experts, help me out please? (Since the code after dpad.run() never ran, I don't know if it works, it may be all garbage. :P

The strange thing is that this simple test code works with no problem:

Cool code:

import threading
import time

class thread1(threading.Thread):

    def __init__(self, threadID, start_from):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.i = start_from
        self.running = True

    def run(self):
            while self.running:
                time.sleep(1)
                self.i = self.i+1

    def stop(self):
        self.running = False

class thread2(threading.Thread):

    def __init__(self, threadID, start_from):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.i = start_from
        self.running = True

    def run(self):
            while self.running:
                time.sleep(0.5)
                self.i = self.i+10

    def stop(self):
        self.running = False

thread1 = thread1(1, 10)
thread2 = thread2(2, 1)

thread1.start()
thread2.start()

for j in range(30):
    print thread1.i, thread2.i
    time.sleep(0.3)

thread1.stop()
thread2.stop()

The output is

10 1
10 1
10 11
10 11
11 21
11 31
11 31
12 41
12 41
12 51
13 61
13 61
13 71
13 71
14 81
14 91
14 91
15 101
15 101
15 111
16 121
16 121
16 131
16 131
17 141
17 151
17 151
18 161
18 161
18 171


------------------
(program exited with code: 0)
Press return to continue

So there I got the main thread plus the two other run parallel, unlikely to the previous code. What the he'll is going on?

Upvotes: 0

Views: 110

Answers (1)

Muposat
Muposat

Reputation: 1506

Instead of

dpad.run()

do

dpad.start()

When calling run() directly you are skipping the whole threading functionality and using it as a regular class.

Upvotes: 2

Related Questions