Comment quitter Python sans traceback?

277

Je voudrais savoir comment quitter Python sans avoir de vidage traceback sur la sortie.

Je souhaite toujours pouvoir renvoyer un code d'erreur, mais je ne souhaite pas afficher le journal de suivi.

Je veux pouvoir quitter exit(number)sans trace mais en cas d'Exception (pas de sortie) je veux la trace.

Sorin
la source
8
sys.exit () arrête l'exécution sans imprimer de trace, ce qui déclenche une exception ... votre question décrit exactement quel est le comportement par défaut, alors ne changez rien.
Luper Rouch
@Luper Il est très facile de vérifier que sys.exit () lève SystemExit!
Val
4
J'ai dit qu'il n'imprimait pas de traceback, pas qu'il ne déclenche pas d'exception.
Luper Rouch
Je pense que cela répond vraiment à la question que vous avez posée: stackoverflow.com/questions/173278/…
Stefan
2
Cette question concerne-t-elle spécifiquement Jython 2.4 ou quelque chose comme ça? Parce que pour les versions modernes de Python (même en 2009, lorsque cela signifiait CPython 2.6 et 3.1, Jython 2.5 et IronPython 2.6), la question n'a aucun sens et les meilleures réponses sont fausses.
abarnert

Réponses:

300

Vous rencontrez probablement une exception et le programme se termine à cause de cela (avec une traceback). La première chose à faire est donc d'attraper cette exception, avant de sortir proprement (peut-être avec un message, exemple donné).

Essayez quelque chose comme ça dans votre 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
la source
2
Il devrait y avoir quelque chose comme "from sys import exit" au début.
voler le
10
Si sys.exit () est appelé dans "truc du programme principal", le code ci-dessus jette la valeur transmise à sys.exit. Notez que sys.exit déclenche SystemExit et la variable "e" contiendra le code de sortie.
bstpierre
5
je suggérerais d'imprimer en stderr sys.stderr.write (msg)
vinilios
14
Je suggère fortement de supprimer les lignes de except Exception:à sys.exit(0), inclusivement. C'est déjà le comportement par défaut pour imprimer une traceback sur toutes les exceptions non gérées et pour quitter après la fin du code, alors pourquoi s'embêter à faire la même chose manuellement?
MestreLion
6
@jkp - Concernant votre commentaire: sys.exit()doit être utilisé pour les programmes. exit()est destiné aux shells interactifs. Voir La différence entre exit () et sys.exit () en Python? .
ire_and_curses
81

Peut-être que vous essayez d'attraper toutes les exceptions et que cela intercepte l' SystemExitexception soulevée par 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 général, utiliser except:sans nommer une exception est une mauvaise idée. Vous attraperez toutes sortes de choses que vous ne voulez pas attraper - comme SystemExit- et cela peut également masquer vos propres erreurs de programmation. Mon exemple ci-dessus est idiot, à moins que vous ne fassiez quelque chose en termes de nettoyage. Vous pouvez le remplacer par:

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

Si vous devez sortir sans augmenter SystemExit:

import os
os._exit(1)

Je fais cela, dans du code qui fonctionne sous unittest et appelle fork(). Unittest obtient lorsque le processus bifurqué augmente SystemExit. C'est définitivement une valise d'angle!

bstpierre
la source
4
-1: Ce code est idiot: pourquoi attraper SystemExitjuste pour appeler sys.exit(e)? La suppression des deux lignes a le même effet. En outre, le nettoyage appartient finally:, non except Exception: ... raise.
MestreLion
@MestreLion: Vous êtes libre de voter, mais si vous lisez mon commentaire juste au-dessus du vôtre, cela n'est vrai que pour la version 2.5+. Si vous avez lu tout mon post, j'ai dit explicitement que le code est idiot et a suggéré exactement ce que vous avez dit dans votre commentaire.
bstpierre
2
Désolé, vous avez raison ... J'ai oublié qu'il y avait une restructuration majeure des exceptions dans Python 2.5. J'ai essayé d'annuler le vote négatif, mais SO ne me le permet que si la réponse est modifiée. Donc, comme nous sommes en 2012 et que Python 2.4 est une histoire ancienne, pourquoi ne pas le modifier et afficher le code (actuel) correct dès le départ, en laissant la méthode antérieure à 2.5 comme note de bas de page? Cela améliorera beaucoup la réponse et je pourrai annuler le vote négatif, et je le ferai avec plaisir. Gagnant-gagnant pour tout le monde :)
MestreLion
@MestreLion: J'ai commencé à éditer comme vous l'avez suggéré, mais cette réponse n'a vraiment de sens que dans le contexte de la question et dans un environnement 2.4. Le downvote ne me dérange pas.
bstpierre
48
import sys
sys.exit(1)
Wojciech Bederski
la source
9

quelque chose comme ça import sys; sys.exit(0)?

Rob
la source
@mestreLion Alors pourquoi obtenir Dets 06 18:53:17 Traceback (dernier appel le plus récent): Fichier "debug_new.py", ligne 4, dans <module> import sys; sys.exit (0) SystemExit: 0 sur org.python.core.PyException.fillInStackTrace (PyException.java:70) dans ma console?
Val
3
@Val: parce que vous n'utilisez pas de console Python standard. Jython n'est pas Python, et il lui semble (ou du moins sa console) gère les exceptions différemment.
MestreLion
4

Il est préférable de ne pas utiliser sys.exit () et de lever / gérer des exceptions pour permettre au programme de se terminer correctement. Si vous souhaitez désactiver le retraçage, utilisez simplement:

sys.trackbacklimit=0

Vous pouvez définir cela en haut de votre script pour écraser toutes les sorties de traceback, mais je préfère l'utiliser avec plus de parcimonie, par exemple "erreurs connues" où je veux que la sortie soit propre, par exemple dans le fichier 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 CalledProcessError est intercepté, la sortie ressemblera à ceci:

[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 une autre erreur se produit, nous obtenons toujours la sortie de traçage complète.

RCross
la source
1
Pour une utilisation sys.trackbacklimitdans Python 3, consultez cette réponse .
Acumenus
4

Utilisez la fonction python intégrée quit () et c'est tout. Pas besoin d'importer de bibliothèque. J'utilise python 3.4

Miled Louis Rizk
la source
2

Je le ferais de cette façon:

import sys

def do_my_stuff():
    pass

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

Qu'en est-il de

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

Pas de traceback et en quelque sorte plus explicite.

agcala
la source
-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
la source
7
Si vous commentiez le code, cela augmenterait la qualité de la réponse.