Exception traceback est masqué si pas relancé 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()
Quand func2
soulève une exception, je reçois la suite de l'exī:
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 où l'exception est à venir à partir de. L'original de trace est perdue.
Comment puis-je préserver original assurer la traçabilité et de la relancer? Je veux voir quelque chose de similaire à 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
Vous devez vous connecter pour publier un commentaire.
Un vide
raise
soulève la dernière exception.Si vous utilisez
raise something
Python a aucun moyen de savoir sisomething
était une exception juste pris avant, ou une nouvelle exception avec une nouvelle trace de la pile. C'est pourquoi il y a le videraise
qui conserve la trace de la pile.Référence ici
Il est possible de modifier et renvoyer une exception:
Donc, si vous voulez modifier l'exception et le renvoyer, vous pouvez le faire:
ValueError
et élever uneRuntimeError
(vous ne pouvez pas le voir, alors, qu'un ValueError a jamais participé), et le seul cas que j'ai rencontré personnellement, quand j'ai voulu conserver la traçabilité en amont, mais faire quelque chose de plus complexe que de simplementraise
sans arguments ont été les cas où je voulais soulever une exception d'un type différent.Vous pouvez obtenir beaucoup d'informations sur l'exception via le
sys.exc_info()
avec le traceback moduleessayer l'extension suivante de votre code.
Ce serait d'imprimer, similaire à ce que tu voulais.
main()
. Je veux la relancer avec l'original assurer la traçabilité et de laisser l'appelant demain()
à y faire face (par exemple, l'ignorer, de l'impression à la console, pour les sauvegarder dans la base de données, etc). Jochen la solution a fonctionné.print
à quelque chose commeraise exc_type.with_traceback(exc_value, exc_traceback)
Tandis que @Jochen réponse qui fonctionne bien dans le cas simple, il n'est pas capable de traiter des cas plus complexes, où vous n'êtes pas directement de capture et de renvoi, mais pour une raison particulière compte tenu de l'exception comme un objet, et souhaitez re-lancer dans un tout nouveau contexte (par exemple, si vous avez besoin de la traiter dans un autre processus).
Dans ce cas, je propose ce qui suit:
Avant de faire cela, de définir un nouveau type d'exception qui vous permettra de renvoyer à plus tard...
Dans le code fautif...
Renvoyer...
Votre fonction principale doit ressembler à ceci:
C'est la façon standard de manipulation (et sur-relancer) des erreurs. Voici une codepad démonstration.
except Exception, err:
peut être contourné avec l'ancienneraise "bad exception"
façon de lever des exceptionsexcept object, err
err = sys.exc_info()[1]
. De toute façon, le point principal a été ré-augmentererr
à l'extérieur deexcept
bloc sans perdre d'origine traceback. Jochen la solution a fonctionné.