Quelle est la différence entre raise
et raise from
en Python?
try:
raise ValueError
except Exception as e:
raise IndexError
qui donne
Traceback (most recent call last):
File "tmp.py", line 2, in <module>
raise ValueError
ValueError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "tmp.py", line 4, in <module>
raise IndexError
IndexError
et
try:
raise ValueError
except Exception as e:
raise IndexError from e
qui donne
Traceback (most recent call last):
File "tmp.py", line 2, in <module>
raise ValueError
ValueError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "tmp.py", line 4, in <module>
raise IndexError from e
IndexError
python
python-3.x
syntax
exception-handling
félin noir
la source
la source
raise IndexError from None
, disons.raise IndexError from False
soulève unTypeError
, pas unIndexError
. Fait ma journée.Réponses:
La différence est que lorsque vous utilisez
from
, l'__cause__
attribut est défini et le message indique que l'exception a été directement causée par . Si vous omettez,from
alors no__cause__
est défini, mais l'__context__
attribut peut également être défini et le suivi affiche alors le contexte comme lors de la gestion de quelque chose d'autre s'est produit .La définition de
__context__
se produit si vous avez utiliséraise
dans un gestionnaire d'exceptions; si vous avez utiliséraise
n'importe où ailleurs, no__context__
est défini non plus.Si a
__cause__
est défini, un__suppress_context__ = True
indicateur est également défini sur l'exception; lorsque__suppress_context__
est défini surTrue
, le__context__
est ignoré lors de l'impression d'une trace.Lorsque vous déclenchez à partir d'un gestionnaire d'exceptions où vous ne voulez pas afficher le contexte (ne voulez pas qu'un message lors de la gestion d'une autre exception s'est produit ), utilisez
raise ... from None
pour définir__suppress_context__
surTrue
.En d'autres termes, Python définit un contexte sur les exceptions afin que vous puissiez introspecter où une exception a été déclenchée, vous permettant de voir si une autre exception a été remplacée par elle. Vous pouvez également ajouter une cause à une exception, en rendant le traçage explicite sur l'autre exception (utilisez un libellé différent), et le contexte est ignoré (mais peut toujours être introspectionné lors du débogage). L'utilisation
raise ... from None
vous permet de supprimer le contexte en cours d'impression.Voir la documentation de la
raise
déclaration :Consultez également la documentation sur les exceptions intégrées pour plus de détails sur le contexte et les informations de cause attachées aux exceptions.
la source
from
et__cause__
au lieu de l'implicite__context__
? Y a-t-il des cas où l'on attacherait une exception différente de celle interceptée par leexcept
?DatabaseError
si l'ouverture de la base de données échoue. Mais si l'échec est le résultat d'unIOError
échec de l'ouverture d'un fichier ou d'unHTTPError
échec du fonctionnement d'une URL, c'est le contexte que vous souhaitez inclure explicitement, de sorte que le développeur utilisant l'API puisse déboguer la raison. À ce moment-là, vous utilisezraise DatabaseError from original_exception
.IOError
ou la transmettreHTTPError
à ses consommateurs, il devra alors l'utiliserraise NewException from databaseexception.__cause__
, en utilisant désormais une exception différente deDatabaseException
celle qu'il vient de capturer.foo
et que vous voulez soulever une nouvelle exceptionbar
? Ensuite, vous pouvez utiliserraise bar from foo
et avoir l'état Python qui afoo
directement causébar
. Si vous ne l' utilisez pasfrom foo
, Python imprimera toujours les deux, mais déclarera que lors de la gestionfoo
, abar
été déclenché , un message différent, destiné à signaler un bogue possible dans la gestion des erreurs.