{{tag>dev python exceptions}}
====== Python: les exceptions ======
* Une exception n'est pas une fatalité, c'est un mécanisme de communication d'erreur tout à fait normal dans un programme et on est capable de la capturer et d'y réagir.
* Les exceptions fournissent de l'information sur l'erreur qui se produit, c'est donc un mécanisme de notification d'erreur très utile.
* Le mécanisme d'exception étant très efficace, il est couramment utilisé pour le fonctionnement normal d'un programme.
Lorsque l'exception est levée, elle donne la raison de l'erreur et elle permet également de situer cette erreur dans le contexte d’exécution du programme. Elle conduit à l'interruption du programme si elle n'est pas explicitement capturée.
On capture les exception via le bloc **try...except**. Toutes les instructions présentes dans le bloc try sont évaluées et les exceptions produites vont être comparées à celles gérées dans le bloc except. Dans le bloc du except, on précise l'exception que l'on souhaite prendre en compte et le code qui doit s'exécuter lorsque l'exception se produit.
On capture l'exception, on produit un comportement approprié réagissant à cette exception et on continue l’exécution normale du programme.
On peut ajouter autant de close **except** que nécessaire pour réagir aux exceptions pouvant être levées par un seul bloc try.
En Python on peut définir une close **excpet** sans préciser aucun type d' exception. C'est dans la majorité des cas une très mauvaise pratique car la close va masquer (en capturant) toutes les exceptions produites par le code sans y réagir spécifiquement.
De manière générale on capture toujours les exceptions que l'on a étudié et prévu dans notre code et on laisse remonter les exceptions non prévues.
Une caractéristique importante des exceptions est qu'elles "bubble": elles remontent la pile d’exécution jusqu’à arrêter le programme (c'est le mécanisme de bubbling). La pile d’exécution contient la liste ordonnée des fonctions qui ont été appelées par le programme mais qui n'ont pas encore retourné de résultat et donc qui restent en cours d’exécution. L'exception lorsqu'elle se produit au sein d'une fonction arrête son exécution et remonte la pile d’exécution jusqu’à ce qu'elle soit capturée ou si elle atteint le haut de la pile arrête l’exécution du programme.
Ce mécanisme de bubbling à deux avantages majeurs:
* on peut capturer et gérer l’exception n'importe où le long de la pile d’exécution du programme.
* La trace permet de savoir exactement le cheminement de l’exception et fournit des informations précieuses pour le diagnostic du problème dans le programme.
Une bonne pratique est de capturer les exceptions bien identifiées au plus près de l'endroit où elles se produisent dans le code afin d'avoir les réactions les plus appropriées à l'origine du problème.
Pour connaître la liste des exceptions pouvant être produites, il faut lire la documentation des modules et objets que l'on utilise.
try
# Bloc d'instructions pouvant produire
# une ou plusieurs exceptions
...
...
except TypeExceptionA:
# Instructions spécifiques de réaction
# à l' exception A
...
...
except TypeExceptionB:
# Instructions spécifiques de réaction
# à l' exception B
...
...
else:
# Bloc d’instructions exécuté si aucune
# exception n'est produite
...
...
finally:
# Bloc d'instruction exécuté quoi qu'il arrive
...
...
Le bloc **finally** est intéressant: il permet de définir un bloc pouvant être exécuté par une une fonction juste après le return.
def return_with_finally(number):
try:
# le return est dans le bloc try
# meme si aucune exception n'est produite pas l'instruction
# le bloc finally sera exécuté après le return
return 1/number
except ZeroDivisionError as e:
print(f"OOPS, {type(e)}, {e}")
return("zero-divide")
finally:
print("on passe ici même si on a vu un return")
L'utilisation du bloc **else** est préférable à l'ajout d'instructions supplémentaires dans le bloc **try**. Cela empêche la capture accidentelle d’exceptions levées par le les instructions du bloc else qui ne seront pas interceptées par le bloc try..except courant.
Le langage Python intègre une [[https://docs.python.org/3/library/exceptions.html#exception-hierarchy|hiérarchie d'exceptions]] directement exploitable.
===== Références =====
* https://docs.python.org/3/library/exceptions.html