web-dev-qa-db-fra.com

rethrowing python exception. Lequel attraper?

J'apprends à utiliser python. Je viens de découvrir cet article: http://nedbatchelder.com/blog/200711/rethrowing_exceptions_in_python.html Il décrit la reprise des exceptions en python, comme ceci:

try:
    do_something_dangerous()
except:
    do_something_to_apologize()
    raise

Puisque vous relancez l'exception, il doit y avoir une instruction "catch-except" externe. Mais maintenant, je réfléchissais. Que faire si do_something_to_apologize () à l'intérieur de l'exception génère une erreur. Lequel sera attrapé dans le "catch-except" extérieur? Celui que vous relancez ou celui lancé par do_something_to_apologize ()? Ou l'exception avec le taux de protection le plus élevé sera-t-elle interceptée en premier?

25
Bosiwow

Essayez-le et voyez:

def failure():
    raise ValueError, "Real error"

def apologize():
    raise TypeError, "Apology error"

try:
    failure()
except ValueError:
    apologize()
    raise

Le résultat:

Traceback (most recent call last):
  File "<pyshell#14>", line 10, in <module>
    apologize()
  File "<pyshell#14>", line 5, in apologize
    raise TypeError, "Apology error"
TypeError: Apology error

La raison: l'erreur "réelle" de la fonction d'origine a déjà été détectée par le except. apologize déclenche une nouvelle erreur avant que raise ne soit atteint. Par conséquent, la raise dans la clause except n'est jamais exécutée et seule l'erreur d'excuse se propage vers le haut. Si apologize déclenche une erreur, Python n'a aucun moyen de savoir que vous alliez déclencher une exception différente après apologize.

Notez que dans Python 3, le traceback mentionnera les deux exceptions, avec un message expliquant comment la seconde est apparue:

Traceback (most recent call last):
  File "./prog.py", line 9, in <module>
  File "./prog.py", line 2, in failure
ValueError: Real error

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./prog.py", line 11, in <module>
  File "./prog.py", line 5, in apologize
TypeError: Apology error

Cependant, la deuxième exception (l'exception "d'excuses") est toujours la seule qui se propage vers l'extérieur et peut être interceptée par une clause except de niveau supérieur. L'exception d'origine est mentionnée dans le retraçage mais est subsumée dans la dernière et ne peut plus être interceptée.

48
BrenBarn

L'exception levée par do_something_to_apologize () sera interceptée. La ligne contenant raise ne s'exécutera jamais, en raison de l'exception levée par do_something_to_apologize. De plus, je ne crois pas qu'il y ait une idée de "priorité" dans les exceptions python.

7
ibebrett