Wie verlasse ich Python ohne Traceback?

277

Ich möchte wissen, wie ich Python beenden kann, ohne einen Traceback-Dump für die Ausgabe zu haben.

Ich möchte weiterhin einen Fehlercode zurückgeben können, aber das Traceback-Protokoll nicht anzeigen.

Ich möchte in der Lage sein, exit(number)ohne Trace zu beenden, aber im Falle einer Ausnahme (kein Exit) möchte ich den Trace.

Sorin
quelle
8
sys.exit () stoppt die Ausführung, ohne eine Rückverfolgung zu drucken, und das Auslösen einer Ausnahme ... Ihre Frage beschreibt genau das Standardverhalten. Ändern Sie also nichts.
Luper Rouch
@Luper Es ist sehr einfach zu überprüfen, ob sys.exit () SystemExit auslöst!
Val
4
Ich sagte, es wird kein Traceback gedruckt, nicht, dass es keine Ausnahme auslöst.
Luper Rouch
Ich denke, dass dies wirklich die Frage beantwortet, die Sie gestellt haben: stackoverflow.com/questions/173278/…
Stefan
2
Ist diese Frage speziell für Jython 2.4 oder so ähnlich? Denn für moderne Versionen von Python (selbst im Jahr 2009, als dies CPython 2.6 und 3.1, Jython 2.5 und IronPython 2.6 bedeutete) macht die Frage keinen Sinn und die Top-Antworten sind falsch.
abarnert

Antworten:

300

Vermutlich tritt eine Ausnahme auf und das Programm wird aus diesem Grund beendet (mit einem Traceback). Das erste, was Sie tun müssen, ist, diese Ausnahme abzufangen, bevor Sie sie sauber beenden (möglicherweise mit einer Meldung, Beispiel angegeben).

Versuchen Sie so etwas in Ihrer mainRoutine:

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
quelle
2
Am Anfang sollte es so etwas wie "from sys import exit" geben.
Rob
10
Wenn sys.exit () in "main program stuff" aufgerufen wird, wirft der obige Code den an sys.exit übergebenen Wert weg. Beachten Sie, dass sys.exit SystemExit auslöst und die Variable "e" den Exit-Code enthält.
Bstpierre
5
Ich würde vorschlagen, in stderr sys.stderr.write (msg) zu
drucken
14
Ich empfehle dringend , die Zeilen von except Exception:bis sys.exit(0)einschließlich zu entfernen . Es ist bereits das Standardverhalten, einen Traceback für alle nicht behandelten Ausnahmen zu drucken und nach dem Ende des Codes zu beenden. Warum also das Gleiche manuell tun?
MestreLion
6
@jkp - In Bezug auf Ihren Kommentar: sys.exit()sollte für Programme verwendet werden. exit()ist für interaktive Shells gedacht. Siehe Der Unterschied zwischen exit () und sys.exit () in Python? .
ire_and_curses
81

Vielleicht versuchen Sie, alle Ausnahmen abzufangen, und dies fängt die SystemExitAusnahme ab, die von ausgelöst wurde 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

Im Allgemeinen ist die Verwendung except:ohne Benennung einer Ausnahme eine schlechte Idee. Sie werden alle Arten von Dingen fangen, die Sie nicht fangen möchten - wie SystemExit- und es kann auch Ihre eigenen Programmierfehler maskieren. Mein Beispiel oben ist albern, es sei denn, Sie tun etwas in Bezug auf die Bereinigung. Sie könnten es ersetzen durch:

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

Wenn Sie beenden müssen, ohne zu erhöhen SystemExit:

import os
os._exit(1)

Ich mache das in Code, der unter unittest läuft und aufruft fork(). Unittest wird, wenn der gegabelte Prozess ausgelöst wird SystemExit. Dies ist definitiv ein Eckfall!

bstpierre
quelle
4
-1: Dieser Code ist albern: Warum SystemExitnur fangen, um anzurufen sys.exit(e)? Das Entfernen beider Zeilen hat den gleichen Effekt. Auch Bereinigung gehört finally:nicht dazu except Exception: ... raise.
MestreLion
@MestreLion: Du kannst frei abstimmen, aber wenn du meinen Kommentar direkt über deinem liest, gilt das nur für 2.5+. Wenn Sie meinen gesamten Beitrag gelesen haben, habe ich ausdrücklich gesagt, dass der Code albern ist, und genau das vorgeschlagen, was Sie in Ihrem Kommentar gesagt haben.
Bstpierre
2
Entschuldigung, Sie haben Recht ... Ich habe vergessen, dass es in Python 2.5 eine umfassende Umstrukturierung von Ausnahmen gab. Ich habe versucht, die Abwertung rückgängig zu machen, aber SO erlaubt mir dies nur, wenn die Antwort bearbeitet wird. Da wir 2012 sind und Python 2.4 eine alte Geschichte ist, können Sie es bearbeiten und den richtigen (aktuellen) Code im Voraus anzeigen, wobei die Methode vor 2.5 als Fußnote verbleibt. Es wird die Antwort sehr verbessern und ich werde in der Lage sein, die Abwertung rückgängig zu machen, und werde dies gerne tun. Win-Win für alle :)
MestreLion
@MestreLion: Ich habe mit der Bearbeitung begonnen, wie Sie vorgeschlagen haben, aber diese Antwort ist wirklich nur im Kontext der Frage und einer 2.4-Umgebung sinnvoll. Die Ablehnung stimmt mich nicht auf.
Bstpierre
48
import sys
sys.exit(1)
Wojciech Bederski
quelle
9

so etwas wie import sys; sys.exit(0)?

rauben
quelle
@mestreLion Warum bekomme ich dann Dets 06 18:53:17 Traceback (letzter Aufruf zuletzt): Datei "debug_new.py", Zeile 4, in <module> import sys; sys.exit (0) SystemExit: 0 bei org.python.core.PyException.fillInStackTrace (PyException.java:70) in meiner Konsole?
Val
3
@Val: weil Sie keine Standard-Python-Konsole verwenden. Jython ist kein Python und es sieht so aus, als würde es (oder zumindest seine Konsole) Ausnahmen anders behandeln.
MestreLion
4

Es ist viel besser, die Verwendung von sys.exit () zu vermeiden und stattdessen Ausnahmen auszulösen / zu behandeln, damit das Programm sauber beendet werden kann. Wenn Sie den Traceback deaktivieren möchten, verwenden Sie einfach:

sys.trackbacklimit=0

Sie können dies oben in Ihrem Skript festlegen, um alle Traceback-Ausgaben zu quetschen. Ich bevorzuge es jedoch, es sparsamer zu verwenden, z. B. "bekannte Fehler", bei denen die Ausgabe sauber sein soll, z. B. in der Datei 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."

Wenn CalledProcessError abgefangen wird, sieht die Ausgabe folgendermaßen aus:

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

Wenn ein anderer Fehler auftritt, erhalten wir immer noch die vollständige Traceback-Ausgabe.

RCross
quelle
1
Informationen zur Verwendung sys.trackbacklimitin Python 3 finden Sie in dieser Antwort .
Acumenus
4

Verwenden Sie die integrierte Python-Funktion quit () und fertig. Sie müssen keine Bibliothek importieren. Ich benutze Python 3.4

Miled Louis Rizk
quelle
2

Ich würde es so machen:

import sys

def do_my_stuff():
    pass

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

Wie wäre es mit

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

Kein Traceback und irgendwie expliziter.

Agcala
quelle
-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
quelle
7
Wenn Sie den Code kommentieren würden, würde dies die Qualität der Antwort erhöhen.