¿Cómo salir de Python sin rastreo?

277

Me gustaría saber cómo salir de Python sin tener un volcado de rastreo en la salida.

Todavía quiero poder devolver un código de error, pero no quiero mostrar el registro de rastreo.

Quiero poder salir usando exit(number)sin seguimiento, pero en caso de una excepción (no una salida) quiero el seguimiento.

Sorin
fuente
8
sys.exit () detiene la ejecución sin imprimir una traza inversa, generar una excepción ... su pregunta describe exactamente cuál es el comportamiento predeterminado, así que no cambie nada.
Luper Rouch
@Luper ¡Es muy fácil verificar que sys.exit () arroje SystemExit!
Val
44
Dije que no imprime un rastreo, no es que no genere una excepción.
Luper Rouch
Creo que esto realmente responde a la pregunta que hizo: stackoverflow.com/questions/173278/…
Stefan
2
¿Es esta pregunta específicamente para Jython 2.4 o algo así? Porque para las versiones modernas de Python (incluso en 2009, cuando eso significaba CPython 2.6 y 3.1, Jython 2.5 y IronPython 2.6), la pregunta no tiene sentido y las respuestas principales son incorrectas.
abarnert

Respuestas:

300

Probablemente encuentre una excepción y el programa se está cerrando debido a esto (con un rastreo). Por lo tanto, lo primero que debe hacer es detectar esa excepción, antes de salir limpiamente (tal vez con un mensaje, ejemplo dado).

Pruebe algo como esto en su mainrutina:

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()
jkp
fuente
2
Debería haber algo como "desde sys import exit" al principio.
robar
10
Si se llama a sys.exit () en "material del programa principal", el código anterior arroja el valor pasado a sys.exit. Observe que sys.exit eleva SystemExit y la variable "e" contendrá el código de salida.
bstpierre
55
Sugeriría imprimir en stderr sys.stderr.write (msg)
vinilios
14
Yo fuertemente sugieren la eliminación de las líneas de except Exception:a sys.exit(0), ambos inclusive. Ya es el comportamiento predeterminado imprimir un rastreo en todas las excepciones no manejadas y salir después de que finalice el código, entonces, ¿por qué molestarse en hacer lo mismo manualmente?
MestreLion
66
@jkp - Con respecto a tu comentario: sys.exit()debe usarse para programas. exit()está destinado a proyectiles interactivos. Ver ¿ La diferencia entre exit () y sys.exit () en Python? .
ire_and_curses
81

¿Quizás estás tratando de atrapar todas las excepciones y esto está atrapando la SystemExitexcepción planteada por 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

En general, usar except:sin nombrar una excepción es una mala idea. Capturará todo tipo de cosas que no desea atrapar, como SystemExit, y también puede enmascarar sus propios errores de programación. Mi ejemplo anterior es tonto, a menos que esté haciendo algo en términos de limpieza. Puedes reemplazarlo con:

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

Si necesita salir sin subir SystemExit:

import os
os._exit(1)

Hago esto, en un código que se ejecuta en unittest y llamadas fork(). Unittest se obtiene cuando se eleva el proceso bifurcado SystemExit. ¡Este es definitivamente un caso de esquina!

bstpierre
fuente
44
-1: Este código es tonto: ¿por qué atrapar SystemExitsolo para llamar sys.exit(e)? Eliminar ambas líneas tiene el mismo efecto. Además, la limpieza pertenece a finally:, no except Exception: ... raise.
MestreLion
@MestreLion: Eres libre de votar, pero si lees mi comentario justo encima del tuyo, eso solo es cierto para 2.5+. Si lees toda mi publicación, explícitamente dije que el código es tonto y sugerí exactamente lo que dijiste en tu comentario.
bstpierre
2
Lo siento, tienes razón ... Olvidé que había una reestructuración importante de excepciones en Python 2.5. Traté de deshacer el voto negativo, pero SO solo me permite hacerlo si se edita la respuesta. Entonces, dado que estamos en 2012 y Python 2.4 es historia antigua, ¿por qué no editarlo y mostrar el código correcto (actual) por adelantado, dejando el método anterior a 2.5 como una nota al pie? Mejorará mucho la respuesta y podré deshacer el voto negativo, y con mucho gusto lo haré. Ganar-ganar para todos :)
MestreLion
@MestreLion: Comencé a editar como usted sugirió, pero esta respuesta realmente solo tiene sentido en el contexto de la pregunta y en un entorno 2.4. El voto negativo no me molesta.
bstpierre
48
import sys
sys.exit(1)
Wojciech Bederski
fuente
9

algo así import sys; sys.exit(0)?

robar
fuente
@mestreLion Entonces, ¿por qué obtengo Dets 06 18:53:17 Traceback (última llamada más reciente): Archivo "debug_new.py", línea 4, en <module> import sys; sys.exit (0) SystemExit: 0 en org.python.core.PyException.fillInStackTrace (PyException.java:70) en mi consola?
Val
3
@Val: porque no estás usando una consola estándar de Python. Jython no es Python, y parece que (o al menos su consola) maneja las excepciones de manera diferente.
MestreLion
4

Es una práctica mucho mejor evitar usar sys.exit () y, en su lugar, generar / manejar excepciones para permitir que el programa termine limpiamente. Si desea desactivar el rastreo, simplemente use:

sys.trackbacklimit=0

Puede configurar esto en la parte superior de su secuencia de comandos para aplastar toda la salida de rastreo, pero prefiero usarla con más moderación, por ejemplo, "errores conocidos" donde quiero que la salida esté limpia, por ejemplo, en el archivo 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."

Si se detecta CalledProcessError, el resultado se verá así:

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

Si se produce cualquier otro error, todavía obtenemos la salida de rastreo completo.

RCross
fuente
1
Para usar sys.trackbacklimiten Python 3, vea esta respuesta .
Acumenus
4

Use la función de pitón incorporada quit () y listo. No es necesario importar ninguna biblioteca. Estoy usando python 3.4

Miled Louis Rizk
fuente
2

Lo haría de esta manera:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)
Karl W.
fuente
0

Qué pasa

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

Sin rastreo y de alguna manera más explícito.

agcala
fuente
-8
# 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
Brian Zimmerman
fuente
77
Si comenta el código, aumentaría la calidad de la respuesta.