sorin
sorin

Reputation: 170410

How to exit from Python without traceback?

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.

Upvotes: 310

Views: 669796

Answers (11)

RCross
RCross

Reputation: 5118

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.

Upvotes: 6

Aten CHEN
Aten CHEN

Reputation: 1

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

Upvotes: 0

IlliakaillI
IlliakaillI

Reputation: 1558

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)

Upvotes: 19

user3103059
user3103059

Reputation:

What about

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

No traceback and somehow more explicit.

Upvotes: -1

Miled Louis Rizk
Miled Louis Rizk

Reputation: 123

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

Upvotes: 3

bstpierre
bstpierre

Reputation: 31206

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!

Upvotes: 90

Karl W.
Karl W.

Reputation: 21

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)

Upvotes: 2

Brian Zimmerman
Brian Zimmerman

Reputation: 1

# 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

Upvotes: -9

jkp
jkp

Reputation: 81278

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()

Upvotes: 322

rob
rob

Reputation: 37644

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

Upvotes: 10

Wojciech Bederski
Wojciech Bederski

Reputation: 3922

import sys
sys.exit(1)

Upvotes: 48

Related Questions