4

I'm creating sort of a interactive command line in python. I have something like this:

def complete_menu():
    while True:
        cmd = input('cmd> ')
        if cmd == "help":
            print('help')
        elif cmd == "?":
            print('?')

When the user presses CTRL-C, instead of exiting the program I'm trying to make it so that it prints "please type exit to exit" and goes back to the while True. I have something like this at the moment:

if __name__ == "__main__":
    try:
       main()
    except KeyboardInterrupt:
        print('Please use exit to exit')
        complete_menu()

Although this works, there is a number of issues. For one, when CTRL-C is pressed the first time, it prints out the text and works perfectly. However, the second time the user presses CTRL-C, it exists with a bunch of messy text like any other program after pressing CTRL-C. Can this be fixed?

1 Answer 1

4

The better way to do this is to register a signal handler:

import signal

def handler(signum, frame):
    print("Please use exit to exit")
    # or: just call sys.exit("goodbye")

...

def main():
    signal.signal(signal.SIGINT, handler)  # prevent "crashing" with ctrl+C
    ...


if __name__ == "__main__":
    main()

Now when a Ctrl+C is received in your code, instead of a KeyboardInterrupt exception being raised, the function handler will be executed. This is a basic example, customize the code within handler to do what you want.

Note: My recommendation is to actually let the user exit with Ctrl+C, i.e. execute any cleanup code that you might need to run and then call sys.exit here. Programs that require a stronger signal to kill are annoying.

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

3 Comments

Much cleaner solution than the naive alternative of while True and provides flexibility of handling other low-level stuff such as Out-of-Memory reaper trying to kill the app (SIGKILL) or making a process go to sleep (SIGTSTP, SIGSTOP, SIGTTIN, SIGTTOU) or waking it up (SIGCONT).
"My recommendation is to actually let the user exit with Ctrl+C ... Programs that require a stronger signal to kill are annoying." -- I see your point, but it depends on the program. If OP's program calls other programs or keeps variables, exiting on Ctrl+C would be annoying, and it would be better to exit on Ctrl+D.
Yes, well, that's why it should do its cleanup on SIGINT. If a program ignores Ctrl+C then it's a safe bet that a Ctrl+\ (SIGQUIT) may be coming soon after.. Correctly handling Ctrl+C doesn't preclude you from also supporting the Ctrl+D (EOF) usage for interactive programs.

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.