76 votes

La trace d'exception est masquée si elle n'est pas relancée immédiatement

J'ai un morceau de code similaire à ceci:

 import sys

def func1():
    func2()

def func2():
    raise Exception('test error')

def main():
    err = None

    try:
        func1()
    except:
        err = sys.exc_info()[1]
        pass

    # some extra processing, involving checking err details (if err is not None)

    # need to re-raise err so caller can do its own handling
    if err:
        raise err

if __name__ == '__main__':
    main()
 

Lorsque func2 lève une exception, je reçois la trace suivante:

 Traceback (most recent call last):
  File "err_test.py", line 25, in <module>
    main()
  File "err_test.py", line 22, in main
    raise err
Exception: test error
 

D'ici je ne vois pas d'où vient l'exception. Le suivi d'origine est perdu.

Comment puis-je conserver le traçage d'origine et le relancer? Je veux voir quelque chose de semblable à ceci:

 Traceback (most recent call last):
  File "err_test.py", line 26, in <module>
    main()
  File "err_test.py", line 13, in main
    func1()
  File "err_test.py", line 4, in func1
    func2()
  File "err_test.py", line 7, in func2
    raise Exception('test error')
Exception: test error
 

128voto

Jochen Ritzel Points 42916

Un raise vide déclenche la dernière exception.

 # need to re-raise err so caller can do its own handling
if err:
    raise
 

Si vous utilisez raise something Python n'a aucun moyen de savoir si something était une exception interceptée auparavant ou une nouvelle exception avec une nouvelle trace de pile. C'est pourquoi il existe un raise vierge qui conserve la trace de la pile.

71voto

qris Points 1649

Il est possible de modifier et renvoyer une exception:

Si aucune des expressions sont présents, soulever re-soulève la dernière exception que a été active dans le champ d'application actuel. Si aucune exception n'est active dans le champ d'application actuel, une exception TypeError est indique que c'est un message d'erreur (si en cours d'exécution en vertu de l'INACTIVITÉ, une File d'attente.Vide exception est levée au lieu de cela).

Sinon, augmenter évalue les expressions d'obtenir trois objets, à l'aide Aucun comme la valeur de omis expressions. Les deux premiers objets sont utilisé pour déterminer le type et la valeur de l'exception.

Si un troisième objet est présent, et non pas, il doit être un traceback objet (voir La section le type standard de la hiérarchie), et il est substituer à la place de l'emplacement actuel comme le lieu où le exception s'est produite. Si le troisième objet est présent et pas un traceback objet ou Aucune, une exception TypeError est soulevée.

Les trois-expression formulaire de relance est utile de re-lever une exception de manière transparente dans un à l'exception de la clause, mais qui posent avec aucune expression doit être préférée si l' l'exception à être re-soulevé a été le plus récemment active exception dans le champ d'application actuel.

Donc, si vous voulez modifier l'exception et le renvoyer, vous pouvez faire ceci:

try:
    buggy_code_which_throws_exception()
except Exception as e:
    raise Exception, "The code is buggy: %s" % e, sys.exc_info()[2]

8voto

Senthil Kumaran Points 14934

Vous pouvez obtenir beaucoup d'informations sur l'exception via le sys.exc_info() avec le module de traçage

essayez l'extension suivante à votre code.

 import sys
import traceback

def func1():
    func2()

def func2():
    raise Exception('test error')

def main():

    try:
        func1()
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        # Do your verification using exc_value and exc_traceback

        print "*** print_exception:"
        traceback.print_exception(exc_type, exc_value, exc_traceback,
                                  limit=3, file=sys.stdout)

if __name__ == '__main__':
    main()
 

Ce serait imprimer, semblable à ce que vous vouliez.

 *** print_exception:
Traceback (most recent call last):
  File "err_test.py", line 14, in main
    func1()
  File "err_test.py", line 5, in func1
    func2()
  File "err_test.py", line 8, in func2
    raise Exception('test error')
Exception: test error
 

2voto

Gabi Purcaru Points 15158

Votre fonction principale doit ressembler à ceci:

 def main():
    try:
        func1()
    except Exception, err:
        # error processing
        raise
 

C’est le moyen standard de traiter (et de relancer) les erreurs. Voici une démonstration du codepad.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X