1

I am looking for a way to stop a script from running upon user input without getting cluttered exception output on screen and without reraising either. I like the sys.exit() approach, it achieves exactly what I want when running python3 myscript.py , However this also kills my repl if I am running the function interactively, and this is what I want to avoid.

An example would be:

def wait_input(message,timeout):
    print (message)
    i, o, e = select.select( [sys.stdin], [], [], timeout )
    if (i):
        return sys.stdin.readline().strip()
    else:
        return ""

def user_checkpoint(question, accepted_answers=("y","yes")  ):
   answer = wait_input(question,3600).lower() 
   if answer not in accepted_answers:
       print('Abort')
       somethinglike.sys.exit()

> user_checkpoint('keep running?')
n
Abort
>

important: note that I am still in repl after Abort, which does not happen if I actually do use sys.exit() in the code.

Fabri Ba
  • 119
  • 9

1 Answers1

0

Apparently, it's possible to tell if Python is in interactive mode, as shown in Tell if Python is in interactive mode. So, how about this:

def is_interactive():
    try:
        return sys.ps1 and True
    except AttributeError:
        return False

def user_checkpoint(question, accepted_answers=("y","yes")  ):
    answer = wait_input(question,3600).lower() 
    if answer not in accepted_answers:
        print('Abort')
        if is_interactive():
            sys.tracebacklimit = 0  # edit 1
            raise KeyboardInterrupt
        else:
            sys.exit()

Edit 2:

Here is another way that might work, from Capture keyboardinterrupt in Python without try-except: Using a custom context manager.

class CleanExit():
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        if exc_type is KeyboardInterrupt:
            return True
        return exc_type is None

with CleanExit():
    print('hi')
    a = input()  # Ctrl-C here
    print(a) 
sammy
  • 857
  • 5
  • 13
  • Thank you Sammy, unfortunately in this case a `raise KeyboardInterrupt` won't exit cleanly tho: it will still throw a lot of traceback text that Ideally I would like to hide – Fabri Ba Dec 07 '19 at 16:30