0

I have this program that should take the user input (an application name installed) and then it will open the application with subprocess.Popen() . All posibles application names are in a dictionary as keys, and the value is the path to the application .exe file. I'm using a try/Exception to see if there will be a KeyError (if the input name doens't exist in the dictionary).

So the programm should take the user input, see if the application name is in the dictionary, and then open the application. If the name isn't on the dictionary, it will give an error message and then ask for a name again.

But when I enter a non-existent name n times, it will run the finally block n times too. How to solve this?

import subprocess

apps ={

"vlc":"app_path\\vlc.exe",
"sublime":"app_path\\sublime_text.exe",
"chrome":"app_path\\chrome.exe",
"opera":"app_path\\launcher.exe",
"torrent":"app_path.\\qbittorrent.exe"
}

def test():
    answer = str(input("What program do you want to run: ")).lower()
    try:
        print(apps[answer])

    except KeyError:
        print(f"{answer.capitalize()} application unknown. Try again with a valid application name")
        print("===============================================================")
        test()
    
    except:
        print("==============================")
        print("Unknown error.")

    else:
        subprocess.Popen(apps[answer])

    finally:
        print("===========================================")
        print("FINISHED")

test()

1
  • If you just want to exit after getting a wrong input, you can use quit() Commented May 29, 2021 at 11:35

1 Answer 1

1

You're using recursion here, so obviously the finally block will run as many times as you enter call the function.

The code within finally is always executed regardless if the try block raises an error or not.

W3Schools has good examples for this: https://www.w3schools.com/python/python_try_except.asp

Instead of using try/except, you can simply use a while loop and apps.get(answer, 'ERROR') or if answer in apps to check if the entered input is in the apps dictionary. The following solution may be optimal.

def test():
    while True:
        answer = input("What program do you want to run: ").lower()
        if answer in apps:
            try:
                res = subprocess.Popen(apps[answer]).communicate()
                print("===========================================")
                print("FINISHED")
                return res
            except:
                print("==============================")
                print("Unknown error.")
        else:
            print(f"{answer.capitalize()} application unknown. Try again with a valid application name")
            print("===============================================================")

test()
Sign up to request clarification or add additional context in comments.

2 Comments

thank you very much. I tried this solution, and worked. But when I typed an app name, it would open but then the script wouldn't finish. I try to eliminate the .communicate(), and it worked again and the script finished without problems. What does the .communicate() do?
.communicate() waits for the program to exit, and then collects stdout and stderr from the program which you can use for further processing. For example if you execute dir or tree it prints file names in the command prompt, and if you want to process that output in python, you can use Popen and then .communicate() to get that stdout.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.