Remove traceback in Python on Ctrl-C

Question:

Is there a way to keep tracebacks from coming up when you hit Ctrl+c,
i.e. raise KeyboardInterrupt in a Python script?

Asked By: Kyle Hotchkiss

||

Answers:

Catch the KeyboardInterrupt:

try:
    # do something
except KeyboardInterrupt:
    pass
Answered By: icktoofay

Catch it with a try/except block:

while True:
   try:
      print "This will go on forever"
   except KeyboardInterrupt:
      pass
Answered By: Manny D
try:
    your_stuff()
except KeyboardInterrupt:
    print("no traceback")
Answered By: ʇsәɹoɈ
import sys
try:
    # your code
except KeyboardInterrupt:
    sys.exit(0) # or 1, or whatever

Is the simplest way, assuming you still want to exit when you get a Ctrl+c.

If you want to trap it without a try/except, you can use a recipe like this using the signal module, except it doesn’t seem to work for me on Windows..

Answered By: agf

Also note that by default the interpreter exits with the status code 128 + the value of SIGINT on your platform (which is 2 on most systems).

    import sys, signal

    try:
        # code...
    except KeyboardInterrupt: # Suppress tracebacks on SIGINT
        sys.exit(128 + signal.SIGINT) # http://tldp.org/LDP/abs/html/exitcodes.html
Answered By: toksaitov

Try this:

import signal
import sys
signal.signal(signal.SIGINT, lambda x, y: sys.exit(0))

This way you don’t need to wrap everything in an exception handler.

Answered By: jleahy
import sys
try:
    print("HELLO")
    english = input("Enter your main launguage: ")
    print("GOODBYE")
except KeyboardInterrupt:
    print("GET LOST")
Answered By: Ryan Bell

suppress exception using context manager:

from contextlib import suppress

def output_forever():
    while True:
        print('endless script output. Press ctrl + C to exit')


if __name__ == '__main__':
    with suppress(KeyboardInterrupt):
        output_forever()
Answered By: Roman Kazakov

According to Proper handling of SIGINT/SIGQUIT, the only way to exit correctly if you’re catching a SIGINT is to subsequently kill yourself with a SIGINT signal (see the section titled "How to be a proper program"). It is incorrect to attempt to fake the proper exit code. For more info about that, check also Why is "Doing an exit 130 is not the same as dying of SIGINT"? over on Unix Stack Exchange.

It seems all the answers here which are exiting zero actually demonstrate programs that misbehave. It’s preferable not to hide that you were interrupted, so that the caller (usually a shell) knows what to do.

In Python, the traceback printout on stderr comes from the default sys.excepthook behaviour. So, to suppress the traceback spam, I’ve opted to tackle the problem directly at the cause by replacing the except hook on keyboard interrupt, and then preserve the correct exit code by re-raising the original exception:

import sys, time

def _no_traceback_excepthook(exc_type, exc_val, traceback):
    pass

def main():
    try:
        # whatever your program does here...
        print("hello world..")
        time.sleep(42)
    except KeyboardInterrupt:
        # whatever cleanup code you need here...
        print("bye")
        if sys.excepthook is sys.__excepthook__:
            sys.excepthook = _no_traceback_excepthook
        raise

if __name__ == "__main__":
    main()

The result is like this:

$ python3 /tmp/example.py
hello world..
^Cbye

$ echo $?
130

If you don’t have any cleanup actions to execute, and all you wanted to do is suppress printing the traceback on interrupt, it may be simpler just to install that by default:

import sys

def _no_traceback_excepthook(exc_type, exc_val, traceback):
    if isinstance(exc_val, KeyboardInterrupt):
        return
    sys.__excepthook__(exc_type, exc_val, traceback)

sys.excepthook = _no_traceback_excepthook
Answered By: wim