Come uscire da Python senza traceback?


277

Vorrei sapere come uscire da Python senza avere un dump di traceback sull'output.

Voglio ancora poter essere in grado di restituire un codice di errore, ma non voglio visualizzare il registro di traceback.

Voglio poter uscire usando exit(number)senza traccia ma in caso di un'eccezione (non un'uscita) voglio la traccia.


8
sys.exit () interrompe l'esecuzione senza stampare una backtrace, sollevando un'eccezione ... la tua domanda descrive esattamente quale sia il comportamento predefinito, quindi non modificare nulla.
Luper Rouch,

@Luper È molto facile verificare che sys.exit () genera SystemExit!
Val

4
Ho detto che non stampa un traceback, non che non solleva un'eccezione.
Luper Rouch,

Penso che questo risponda davvero alla domanda che hai posto: stackoverflow.com/questions/173278/…
Stefan

2
Questa domanda è specifica per Jython 2.4 o qualcosa del genere? Perché per le versioni moderne di Python (anche nel 2009, quando questo significava CPython 2.6 e 3.1, Jython 2.5 e IronPython 2.6), la domanda non ha senso e le risposte migliori sono sbagliate.
abarnert,

Risposte:


300

Probabilmente stai riscontrando un'eccezione e il programma sta uscendo per questo (con un traceback). La prima cosa da fare quindi è catturare quell'eccezione, prima di uscire in modo pulito (magari con un messaggio, esempio fornito).

Prova qualcosa di simile nel tuo 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()

2
Dovrebbe esserci qualcosa come "dall'uscita di importazione sys" all'inizio.
rapina il

10
Se sys.exit () viene chiamato in "roba principale del programma", il codice sopra getta via il valore passato a sys.exit. Si noti che sys.exit genera SystemExit e la variabile "e" conterrà il codice di uscita.
bstpierre,

5
suggerirei di stampare in stderr sys.stderr.write (msg)
vinilios

14
Consiglio vivamente di rimuovere le righe da except Exception:a sys.exit(0), incluso. È già il comportamento predefinito stampare un traceback su tutte le eccezioni non gestite e uscire dopo la fine del codice, quindi perché preoccuparsi di fare lo stesso manualmente?
MestreLion,

6
@jkp - Per quanto riguarda il tuo commento: sys.exit()dovrebbe essere usato per i programmi. exit()è destinato a shell interattive. Vedi La differenza tra exit () e sys.exit () in Python? .
ire_and_curses il

81

Forse stai cercando di cogliere tutte le eccezioni e questo sta cogliendo l' SystemExiteccezione sollevata da 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 generale, usare except:senza nominare un'eccezione è una cattiva idea. Prenderai tutti i tipi di cose che non vuoi catturare - come SystemExit- e può anche mascherare i tuoi errori di programmazione. Il mio esempio sopra è sciocco, a meno che tu non stia facendo qualcosa in termini di pulizia. Puoi sostituirlo con:

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

Se devi uscire senza rilanciare SystemExit:

import os
os._exit(1)

Faccio questo, nel codice che funziona sotto unittest e chiama fork(). Unittest diventa quando si alza il processo biforcato SystemExit. Questo è sicuramente un caso angolare!


4
-1: questo codice è stupido: perché catturare SystemExitsolo per chiamare sys.exit(e)? La rimozione di entrambe le linee ha lo stesso effetto. Inoltre, la pulizia appartiene finally:, non except Exception: ... raise.
MestreLion,

@MestreLion: sei libero di votare, ma se leggi il mio commento appena sopra il tuo, è vero solo per 2.5+. Se leggi tutti i miei post, ho esplicitamente detto che il codice è stupido e ho suggerito esattamente cosa hai detto nel tuo commento.
bstpierre,

2
Scusa, hai ragione ... Ho dimenticato che in Python 2.5 vi era una grande ristrutturazione delle eccezioni. Ho provato a annullare il downvote, ma SO mi permette di farlo solo se la risposta viene modificata. Quindi, dal momento che siamo nel 2012 e Python 2.4 è storia antica, perché non modificarlo e mostrare il codice (attuale) corretto in anticipo, lasciando il metodo pre-2.5 come nota a piè di pagina? Migliorerà molto la risposta e potrò annullare il downvote e lo farò volentieri. Vincente per tutti :)
MestreLion

@MestreLion: ho iniziato a modificare come mi hai suggerito, ma questa risposta ha davvero senso solo nel contesto della domanda e in un ambiente 2.4. Il downvote non mi fa arrabbiare.
bstpierre,


9

qualcosa del genere import sys; sys.exit(0)?


@mestreLion Allora perché ottengo Dets 06 18:53:17 Traceback (ultima chiamata più recente): File "debug_new.py", linea 4, in <module> import sys; sys.exit (0) SystemExit: 0 su org.python.core.PyException.fillInStackTrace (PyException.java:70) nella mia console?
Val

3
@Val: perché non stai utilizzando una console Python standard. Jython non è Python e sembra che (o almeno la sua console) gestisca le eccezioni in modo diverso.
MestreLion,



4

È molto meglio evitare di usare sys.exit () e invece sollevare / gestire le eccezioni per consentire al programma di terminare in modo pulito. Se si desidera disattivare il traceback, utilizzare semplicemente:

sys.trackbacklimit=0

Puoi impostarlo nella parte superiore dello script per eliminare tutto l'output di traceback, ma preferisco usarlo con più parsimonia, ad esempio "errori noti" in cui desidero che l'output sia pulito, ad esempio nel 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."

Se viene catturato CalledProcessError, l'output sarà simile al seguente:

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

Se si verificano altri errori, viene comunque visualizzato l'output di traceback completo.


1
Per l'utilizzo sys.trackbacklimitin Python 3, vedi questa risposta .
Acumenus,

4

Usa la funzione built-in python quit () e il gioco è fatto. Non è necessario importare alcuna libreria. Sto usando Python 3.4


2

Lo farei così:

import sys

def do_my_stuff():
    pass

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

0

Che dire

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

Nessun traceback e in qualche modo più esplicito.


-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

7
Se commentassi il codice, aumenterebbe la qualità della risposta.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.