312

I would like to know how to I exit from Python without having an traceback dump on the output.

I still want want to be able to return an error code but I do not want to display the traceback log.

I want to be able to exit using exit(number) without trace but in case of an Exception (not an exit) I want the trace.

7
  • 10
    sys.exit() stops execution without printing a backtrace, raising an Exception does... your question describes exactly what the default behavior is, so don't change anything. Commented Jul 27, 2009 at 17:43
  • 2
    @Luper It is very easy to check that sys.exit() throws SystemExit! Commented Oct 1, 2012 at 18:45
  • 5
    I said it doesn't print a traceback, not that it doesn't raise an exception. Commented Oct 2, 2012 at 5:45
  • I think that this really answers the question you asked: stackoverflow.com/questions/173278/… Commented Nov 20, 2012 at 19:39
  • 3
    Is this question specifically for Jython 2.4 or something like that? Because for modern versions of Python (even in 2009, when that meant CPython 2.6 and 3.1, Jython 2.5, and IronPython 2.6), the question makes no sense, and the top answers are wrong. Commented Sep 28, 2014 at 2:18

11 Answers 11

322

You are presumably encountering an exception and the program is exiting because of this (with a traceback). The first thing to do therefore is to catch that exception, before exiting cleanly (maybe with a message, example given).

Try something like this in your main routine:

import sys, traceback

def main():
    try:
        do main program stuff here
        ....
    except KeyboardInterrupt:
        print "Shutdown requested...exiting"
    except Exception:
        traceback.print_exc(file=sys.stdout)
    sys.exit(0)

if __name__ == "__main__":
    main()
Sign up to request clarification or add additional context in comments.

12 Comments

If sys.exit() is called in "main program stuff", the code above throws away the value passed to sys.exit. Notice that sys.exit raises SystemExit and the variable "e" will contain the exit code.
i would suggest printing in stderr sys.stderr.write(msg)
I strongly suggest removing the lines from except Exception: to sys.exit(0), inclusive. It is already the default behavior to print a traceback on all non-handled exceptions, and to exit after code ends, so why bother doing the same manually?
@jkp - Regarding your comment: sys.exit() should be used for programs. exit() is intended for interactive shells. See The difference between exit() and sys.exit() in Python?.
@Pierre: But the way this is written, it won't do that—it will print the exception, then exit with no error code. That's almost the exact opposite of what you want.
|
90

Perhaps you're trying to catch all exceptions and this is catching the SystemExit exception raised by sys.exit()?

import sys

try:
    sys.exit(1) # Or something that calls sys.exit()
except SystemExit as e:
    sys.exit(e)
except:
    # Cleanup and reraise. This will print a backtrace.
    # (Insert your cleanup code here.)
    raise

In general, using except: without naming an exception is a bad idea. You'll catch all kinds of stuff you don't want to catch -- like SystemExit -- and it can also mask your own programming errors. My example above is silly, unless you're doing something in terms of cleanup. You could replace it with:

import sys
sys.exit(1) # Or something that calls sys.exit().

If you need to exit without raising SystemExit:

import os
os._exit(1)

I do this, in code that runs under unittest and calls fork(). Unittest gets when the forked process raises SystemExit. This is definitely a corner case!

4 Comments

-1: This code is silly: why catch SystemExit just to call sys.exit(e)? Removing both lines has the same effect. Also, cleanup belongs to finally:, not except Exception: ... raise.
@MestreLion: You're free to downvote, but if you read my comment just above yours, that's only true for 2.5+. If you read all of my post, I explicitly said that the code is silly and suggested exactly what you said in your comment.
Sorry, you're right... I forgot there was a major re-structure of exceptions in Python 2.5. I tried to undo the downvote, but SO only allows me to do so if the answer is edited. So, since we are in 2012 and Python 2.4 is ancient history, why not edit it and show the correct (current) code upfront, leaving the pre-2.5 method as a footnote? It will improve the answer a lot and I'll be able to undo the downvote, and will gladly do so. Win-win for everyone :)
@MestreLion: I started editing as you suggested, but this answer really only makes sense in the context of the question and a 2.4 environment. The downvote doesn't upset me.
48
import sys
sys.exit(1)

Comments

20

The following code will not raise an exception and will exit without a traceback:

import os
os._exit(1)

See this question and related answers for more details. Surprised why all other answers are so overcomplicated.

This also will not do proper cleanup, like calling cleanup handlers, flushing stdio buffers, etc. (thanks to pabouk for pointing this out)

1 Comment

Not suitable for normal exits. This solution bypasses all the Python cleanup code!
10

something like import sys; sys.exit(0) ?

3 Comments

@mestreLion Then why do I get Dets 06 18:53:17 Traceback (most recent call last): File "debug_new.py", line 4, in <module> import sys; sys.exit(0) SystemExit: 0 at org.python.core.PyException.fillInStackTrace(PyException.java:70) in my console?
@Val: because you're not using a standard python console. Jython is not Python, and it looks like it (or at least its console) handles exceptions differently.
6

It's much better practise to avoid using sys.exit() and instead raise/handle exceptions to allow the program to finish cleanly. If you want to turn off traceback, simply use:

sys.tracebacklimit = 0

You can set this at the top of your script to squash all traceback output, but I prefer to use it more sparingly, for example "known errors" where I want the output to be clean, e.g. in the file foo.py:

import sys
from subprocess import *

try:
    check_call([ 'uptime', '--help' ])
except CalledProcessError:
    sys.tracebacklimit = 0
    print "Process failed"
    raise

print "This message should never follow an error."

If CalledProcessError is caught, the output will look like this:

[me@test01 dev]$ ./foo.py
usage: uptime [-V]
    -V    display version
Process failed
subprocess.CalledProcessError: Command '['uptime', '--help']' returned non-zero exit status 1

If any other error occurs, we still get the full traceback output.

2 Comments

For using sys.trackbacklimit in Python 3, see this answer.
Please send error messages to stderr, not stdout. Use this instead: print("Process failed", file=sys.stderr)
3

Use the built-in python function quit() and that's it. No need to import any library. I'm using python 3.4

1 Comment

Please do not use quit() or exit() in your code. These functions are intended only for the interactive Python. See Python exit commands - why so many and when should each be used? You can use sys.exit() or raise SystemExit instead.
2

I would do it this way:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)

Comments

0
import atexit
import inspect
import os
import signal
import sys


def sigint_handler(signal, frame):
    sys.stderr.write('\nInterrupted')
    cleanup(0)


def _cleanup(attr, method, args):
    code = 0
    if hasattr(attr, method):
        try:
            getattr(attr, method)(*args)
        except Exception as exc:
            sys.stderr.write(f"Error cleaning up attribute {repr(attr)}: {exc}")
            code = 1
    return code


def cleanup(code=0):
    for attr in globals().values():
        if not(inspect.isclass(attr) or inspect.isfunction(attr)):
            if not code:
                code |= _cleanup(attr, "__del__", ())
                code |= _cleanup(attr, "__exit__", (None, None, None))
    
    try:
        atexit._run_exitfuncs()
    except Exception as exc:
        sys.stderr.write(f"Error running exit event handlers: {exc}")
        code |= 1
    
    os._exit(code)


signal.signal(signal.SIGINT, sigint_handler)


# -- Maincode down here --

def main():
    pass

# -- Maincode Ends


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.stderr.write('\nInterrupted')
        cleanup(0)

P.S.: The output msgs from the standerd error stream ISN'T A TRACEBACK, but it can be friendly to users

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
-1

What about

import sys
....
....
....
sys.exit("I am getting the heck out of here!")

No traceback and somehow more explicit.

Comments

-9
# Pygame Example  

import pygame, sys  
from pygame.locals import *

pygame.init()  
DISPLAYSURF = pygame.display.set_mode((400, 300))  
pygame.display.set_caption('IBM Emulator')

BLACK = (0, 0, 0)  
GREEN = (0, 255, 0)

fontObj = pygame.font.Font('freesansbold.ttf', 32)  
textSurfaceObj = fontObj.render('IBM PC Emulator', True, GREEN,BLACK)  
textRectObj = textSurfaceObj.get_rect()  
textRectObj = (10, 10)

try:  
    while True: # main loop  
        DISPLAYSURF.fill(BLACK)  
        DISPLAYSURF.blit(textSurfaceObj, textRectObj)  
        for event in pygame.event.get():  
            if event.type == QUIT:  
                pygame.quit()  
                sys.exit()  
        pygame.display.update()  
except SystemExit:  
    pass

1 Comment

If you would comment the code, it would increase the quality of the answer.

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.