Home > other >  Python - if inside of an if
Python - if inside of an if

Time:05-23

My script looks for certain bluetooth state criterias (if it's turned On and if there's no device connected) through the first loop and then sleeps 10 seconds to allow the user to change the bluetooth state and then checks again the same criterias before executing a prompt.

What I don't understand is that when I run the code and change the state before the wait period (10 seconds) end, it still runs the code inside the second if statement.

def bluetoothLoop():
    while True:        
        def bluetooth_msg():
            BT_state = subprocess.run(['''system_profiler SPBluetoothDataType'''], shell=True, capture_output=True, encoding="utf", errors="ignore")
            BT_state = BT_state.stdout
            sound = "Blow"
            title = "TURN OFF BLUETOOTH"
            message = "Wasting energy"
            if "State: On" in BT_state and not "  Connected:" in BT_state:
                time.sleep(10)
                if "State: On" in BT_state and not "  Connected:" in BT_state:
                    command = f'''
                    osascript -e 'display notification "{message}" with title "{title}" sound name "{sound}"'
                    '''
                    os.system(command)
        bluetooth_msg()

CodePudding user response:

You're not refreshing the state after you sleep for 10 seconds. Try

if "State: On" in BT_state and not "  Connected:" in BT_state:
                time.sleep(10)
                BT_state = subprocess.run(['''system_profiler SPBluetoothDataType'''], shell=True, capture_output=True, encoding="utf", errors="ignore")
                BT_state = BT_state.stdout
                if "State: On" in BT_state and not "  Connected:" in BT_state:
                    command = f'''
                    osascript -e 'display notification "{message}" with title "{title}" sound name "{sound}"'
                    '''
                    os.system(command)

You can probably even clean up your code by doing

def bluetoothLoop():
    BT_state = subprocess.run(['''system_profiler SPBluetoothDataType'''], shell=True, capture_output=True, encoding="utf", errors="ignore")
    BT_state = BT_state.stdout
    def bluetooth_msg():
            sound = "Blow"
            title = "TURN OFF BLUETOOTH"
            message = "Wasting energy"
            command = f'''
                    osascript -e 'display notification "{message}" with title "{title}" sound name "{sound}"'
                    '''
            os.system(command)
    while "State: On" in BT_state and not "  Connected:" in BT_state:
        bluetooth_msg()
        time.sleep(10)
        BT_state = subprocess.run(['''system_profiler SPBluetoothDataType'''], shell=True, capture_output=True, encoding="utf", errors="ignore")
        BT_state = BT_state.stdout

Beware I didn't run the code above, so you may need to tweak it a little.

CodePudding user response:

You run the subprocess to get the BT_state before the sleep but you don't run it again after the sleep so the variable BT_state is not updated. Effectively you are checking the same thing twice.

I have refactored your code below to separate out the different pieces in the hope that it is easier to see what is going on.

import subprocess
import time


def check_bt_status():
    output = subprocess.check_output(["system_profiler",
                                      "SPBluetoothDataType"])
    return all([b"Bluetooth Power: On" in output,
                b"Connected: Yes" not in output])
    

def show_msg(title, message, sound):
    apple_script = (f'display notification "{message}"'
                    f'with title "{title}" '
                    f'sound name "{sound}"')
    subprocess.check_output(["osascript", "-e", apple_script])


def bluetooth_loop():
    while True:
        if check_bt_status():
            show_msg("TURN OFF BLUETOOTH", "Wasting energy", "Blow")
        time.sleep(10)

if __name__ == "__main__":
    bluetooth_loop()

Putting the BT state logic in a separate method means that if you need to change that logic, then you only need to change it in one place.

  • Related