Reputation: 170410
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
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
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
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
Reputation:
What about
import sys
....
....
....
sys.exit("I am getting the heck out of here!")
No traceback and somehow more explicit.
Upvotes: -1
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
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
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
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
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