Search code examples
pythonshellpython-2.xstring-comparison

Using if statement when examining results from command line


I am trying to write a GUI for a VPN program called windscribe-cli. I need to distinguish whether the VPN is connected or not.
The result of windscribe status looks like:

windscribe -- pid: 1479, status: running, uptime: 1h 50m, %cpu: 0.0, %mem: 0.4 IP: 143.159.73.130 DISCONNECTED

DISCONNECTED is written in red.

I cannot get a result from if or elif for words written in colour.

I have tried using if elif but they ignore writing in colour. Using print word_list[14] outputs the word in colour.

import sh

def status():

    status = ""
    windscribe_status = sh.windscribe("status")
    word_list = windscribe_status.split()

    if word_list[14] == "CONNECTED":
        status = "connected"
    elif word_list[14] == "DISCONNECTED":
        status = "disconnected"

    return status

print status()

I am expecting to see connected or disconnected but see nothing.


Solution

  • I wouldn't build this around the coloring if I were you. windscribe may be an exception (it's not uncommon), but cli programs typically check to see if their output is a terminal device before writing out terminal escapes to change color. this blog post is written with python examples of writing colored data to terminal, but should work well for getting to know the mechanism behind the color codes and why your word doesn't match what you expect it to. So probably it's best to ignore the color.

    Frankly, using status message isn't ideal either. These status meant for human consumption generally fail to provide consistent enough behavior over time to provide a very reliable interface. Many programs will expose their status in a more program-friendly way - maybe a socket from which you can read the status, or a file, or a different invocation of the cli program. But maybe not - depends on the program. Generally open source programs include these kind of feature because their developers are often experienced in the CLI programming space - proprietary code, less so. But ymmv.

    Anyway, that all notwithstanding, your problem is this:

    word_list = windscribe_status.split()
    

    That's going to split on spaces, but it's not going to exclude the color codes surrounding the colored output. Actually, you can make you program somewhat more robust in the face of changing status messages, and also simpler, by doing something like this:

    if "disconnected" in winscribe_status.lower():
       handle disconnected
    elif "connected" in winscribe_status.lower():
       handle connected
    

    Here, I use in to check for a substring; and I use lower() to insulate myself from future changes to capitalization (not strictly necessary, but it will feel like it was worth doing if the capitalization ever changes).

    Here's a complete example of the procedure with your specifics removed:

    import subprocess
    test_inputs = [
      "I AM DISConnected!",
      "\033[1;31mDISCONNECTED\033[0m",
      "Successfully \033[1;32mConnected\033[0m"
    ]
    for cmd in test_inputs:
      res = subprocess.check_output(["echo",'-n',cmd])
      res = str(res)
      print("Message was: '{}'".format(res))
      if 'disconnected' in res.lower():
        print('Disconnected!')
      elif 'connected' in res.lower():
        print('Connected!')
    

    I run like this. Pyhton3 output looks a little different but the logic still works.

    $ python ./t.py
    Message was: 'I AM DISConnected!'
    Disconnected!
    Message was: 'DISCONNECTED'
    Disconnected!
    Message was: 'Successfully Connected'
    Connected!
    

    Here, the order of the words doesn't matter, nor does their number, or their case, and it works with or without color which it simply ignores. The order matters; obviously 'connected' will match anywhere 'disconnected' matches.