Use same Python variable in multiple if-statements

2.7k views Asked by At

I am having issues with my current Python script. The purpose of the 'progress' variable is take a specific value when it goes through one of the if-loops. But, the program never goes further then the first if-statement. It looks as if every if-statement makes his own variable called 'progress'. Can someone please help me? See code below.

from bottle import run, route, template, error, static_file     
import RPi.GPIO as GPIO                         
import time                             

switch1 = 21        
switch2 = 20        
switch3 = 26        
switch4 = 16        
switch5 = 19        

led1 = 13       
led2 = 12       
led3 = 6        
led4 = 5        
led5 = 25       

GPIO.setmode(GPIO.BCM)                          

GPIO.setup(switch1, GPIO.IN, pull_up_down=GPIO.PUD_UP)          
GPIO.setup(switch2, GPIO.IN, pull_up_down=GPIO.PUD_UP)          
GPIO.setup(switch3, GPIO.IN, pull_up_down=GPIO.PUD_UP)          
GPIO.setup(switch4, GPIO.IN, pull_up_down=GPIO.PUD_UP)          
GPIO.setup(switch5, GPIO.IN, pull_up_down=GPIO.PUD_UP)          

GPIO.setup(led1, GPIO.OUT)                      
GPIO.setup(led2, GPIO.OUT)                      
GPIO.setup(led3, GPIO.OUT)                      
GPIO.setup(led4, GPIO.OUT)                      
GPIO.setup(led5, GPIO.OUT)                      


@route("/")
def hello():
    progress = 0
    while True:
        if progress == 0:
            GPIO.output(led1, False)
            GPIO.output(led2, False)
            GPIO.output(led3, False)
            GPIO.output(led4, False)
            GPIO.output(led5, False)

            progress = 1    
            return template('index.html')

        if (not GPIO.input(switch1)) and progress == 1:     
            GPIO.output(led1, True)
            progress = 2
            return template('video1.html')

        elif (not GPIO.input(switch2)) and progress == 2:   
            GPIO.output(led1, False)
            GPIO.output(led2, True)
            progress = 3
            return template('video2.html')

        elif (not GPIO.input(switch3)) and progress == 3:   
            GPIO.output(led2, False)
            GPIO.output(led3, True)
            progress = 4
            return template('video3.html')

        elif (not GPIO.input(switch4)) and progress == 4:   
            GPIO.output(led3, False)
            GPIO.output(led4, True)
            progress = 5
            return template('video4.html')

        elif (not GPIO.input(switch5)) and progress == 5:   
            GPIO.output(led4, False)
            GPIO.output(led5, True)
            progress = 6
            return template('video5.html')

        elif progress == 6:
            while True:                     
                GPIO.output(led1, True)
                GPIO.output(led2, True)
                GPIO.output(led3, True)
                GPIO.output(led4, True)
                GPIO.output(led5, True)
                time.sleep(0.5)
                GPIO.output(led1, False)
                GPIO.output(led2, False)
                GPIO.output(led3, False)
                GPIO.output(led4, False)
                GPIO.output(led5, False)
                time.sleep(0.5)

                return template('succes.html')

        elif GPIO.input(switch1) and GPIO.input(switch2) and GPIO.input(switch3) and GPIO.input(switch4) and GPIO.input(switch5):
             time.sleep(0.15)  


        else:                           
            GPIO.output(led1, False)
            GPIO.output(led2, False)
            GPIO.output(led3, False)
            GPIO.output(led4, False)
            GPIO.output(led5, False)

            return template('false.html')

        time.sleep(0.05)                    

@route('/<filename>')                           
def server_static(filename):
    return static_file(filename, root='static')

@error(404)                             
def error404(error):
    return("Nothing here, keep searching!")

run(host='0.0.0.0', port=80)                        
3

There are 3 answers

5
Martijn Pieters On BEST ANSWER

You are using if...elif.... Python will pick one matching test (the first if or elif test to match), and never run the other branches.

Thus, altering progress in one of those branches will not cause one of the other branches to then be picked.

If the tests are to be separate, you should not use elif but if for each branch.

However, you exit the view altogether in each branch with a return statement. Your function will not continue, the loop is exited and the next request will always start at the beginning again (where you set progress = 0. If progress is meant to be a global state in your server, you should set it as such. Do note that that is not going to be thread safe, nor is that variable going to be shared across processes if you use a WSGI server that uses multiprocessing to scale.

Since you are controlling a piece of hardware, using a global may be fine, but you need to then constrain your WSGI server to run just the one thread, or you need to use locking to limit this view to one thread at a time.

To make the progress global, add global progress at the top of your function, and put progress = 0 outside the function:

progress = 0

@route("/")
def hello():
    global progress
    if progress == 0:
        GPIO.output(led1, False)
        GPIO.output(led2, False)
        GPIO.output(led3, False)
        GPIO.output(led4, False)
        GPIO.output(led5, False)

        progress = 1    
        return template('index.html')

    if (not GPIO.input(switch1)) and progress == 1:     
        GPIO.output(led1, True)
        progress = 2
        return template('video1.html')

    elif (not GPIO.input(switch2)) and progress == 2:   
        GPIO.output(led1, False)
        GPIO.output(led2, True)
        progress = 3
        return template('video2.html')

    elif (not GPIO.input(switch3)) and progress == 3:   
        GPIO.output(led2, False)
        GPIO.output(led3, True)
        progress = 4
        return template('video3.html')

    elif (not GPIO.input(switch4)) and progress == 4:   
        GPIO.output(led3, False)
        GPIO.output(led4, True)
        progress = 5
        return template('video4.html')

    elif (not GPIO.input(switch5)) and progress == 5:   
        GPIO.output(led4, False)
        GPIO.output(led5, True)
        progress = 6
        return template('video5.html')

    elif progress == 6:
        while True:                     
            GPIO.output(led1, True)
            GPIO.output(led2, True)
            GPIO.output(led3, True)
            GPIO.output(led4, True)
            GPIO.output(led5, True)
            time.sleep(0.5)
            GPIO.output(led1, False)
            GPIO.output(led2, False)
            GPIO.output(led3, False)
            GPIO.output(led4, False)
            GPIO.output(led5, False)
            time.sleep(0.5)

            return template('succes.html')

    elif GPIO.input(switch1) and GPIO.input(switch2) and GPIO.input(switch3) and GPIO.input(switch4) and GPIO.input(switch5):
         time.sleep(0.15)  


    else:                           
        GPIO.output(led1, False)
        GPIO.output(led2, False)
        GPIO.output(led3, False)
        GPIO.output(led4, False)
        GPIO.output(led5, False)

        return template('false.html')

Note that the while loop and the sleep() call are gone. You'll have to put Javascript in the responses instead to reload the page after a timeout instead.

0
Marco On

Isn't the return template('index.html') exiting the function? Since you initialize the progress variable always to o the first if is always executed and exits at the end.

You must do the initialisation of your GPIO.output in a separate function and then you can test on the value of your GPIO.input. No need for the progress variable.

3
The6thSense On

As per bottle documentation return template('') will return the template and stop the that function in this "/"

The variable progress is a local variable you have not assigned any the variable inside the program other than initializing

you have assigned it to 0 so all the time the first if statement will be executed