Quand une erreur se produit dans un script, elle provoque l’arrêt du programme et l’affichage d’un message d’erreur.
Pour éviter cette interruption brutale, on peut appliquer un traitement spécifique. Plus généralement, on peut traiter une situation exceptionnelle dont on ne sait pas forcément où et quand elle va survenir à l’intérieur d’un bloc donné. Plutôt que de parler d’erreur, on emploiera donc le terme “exception”. Et prévoir une réaction adaptée à une exception, c’est la “rattraper”.
Pour le traitement des exceptions, Python offre la clause try: ... except.
La forme la plus simple est la suivante, où le bloc2 est parcouru si une exception (quelle qu’elle soit) est rencontrée dans le bloc1 (cette exception provoque l’arrêt du bloc1 et le passage immédiat au bloc2) :
|
1 2 3 4 |
try : bloc1_dans_lequel_une_exception_peut_survenir except : bloc2_de_rattrapage_de_toutes_les_exceptions |
On peut également prévoir un traitement particulier pour telle ou telle exception. Dans ce cas, on utilisera une construction un peu plus élaborée, du genre :
|
1 2 3 4 5 6 7 8 9 10 11 |
try : bloc1_dans_lequel_une_exception_peut_survenir except nom_de_l_exception_A : blocA_de_rattrapage_de_l_exception_A except nom_de_l_exception_B : blocB_de_rattrapage_de_l_exception_B ... except nom_de_l_exception_Z : blocZ_de_rattrapage_de_l_exception_Z except : # (facultatif) bloc_de_rattrapage_de_toutes_les_exceptions_non_prévues_à_ce_stade |
On peut appliquer un même traitement à plusieurs exceptions. Pour cela, on écrira : except (err1, err2, …):
La construction except peut être complétée par une clause else, exécutée si aucune exception n’a été levée/rattrapée.
Python possède beaucoup d’exceptions prédéfinies (cf http://docs.python.org/3.3/library/exceptions.html)
En voici juste quelques-unes :
IndexError |
se produit si on cherche à accéder à un élément d’une liste, en dehors des limites de celle-ci |
NameError |
se produit quand on évoque une variable (locale ou globale) dont le nom n’existe pas |
SyntaxError |
se produit quand Python échoue à lire une expression dont la syntaxe est erronée |
TypeError |
se produit quand une opération est appliquée à un objet qui n’est pas du type adéquat |
ZeroDivisionError |
se produit quand un calcul arithmétique conduit à une division par 0 |
Le programme ci-dessous demande une expression numérique au clavier, et il renvoie la valeur de cette expression (et s’il y a une erreur, quelle qu’elle soit, il demande à nouveau d’entrer une expression numérique) :
|
1 2 3 4 5 6 7 |
def calcul(): fini = False while not fini: try: result = float(eval(input('Entrez une expression numérique: '))) except: print('Il y a eu une erreur, recommencez') else: fini = True print('Le résultat est:',result) |
Voici un exemple d’utilisation. On entre ici plusieurs expressions erronées. L’erreur n’est jamais la même, mais le traitement indifférencié par try:... except: ne permet pas de s’en rendre compte.
|
1 2 3 4 5 6 7 8 9 |
>>> calcul() Entrez une expression numérique: [1,2,3] Il y a eu une erreur, recommencez Entrez une expression numérique: 1** Il y a eu une erreur, recommencez Entrez une expression numérique: 1/0 Il y a eu une erreur, recommencez Entrez une expression numérique: 1/2+1/3 Le résultat est: 0.8333333333333333 |
On modifie maintenant le programme calcul en affinant un peu le traitement des erreurs. Il y a un message personnalisé pour les exceptions les plus probables, mais la dernière clause except: permet de rattraper toutes les exceptions non traitées à ce stade.
|
1 2 3 4 5 6 7 8 9 10 |
def calcul(): fini = False while not fini: try: result = float(eval(input('Entrez une expression numérique: '))) except (TypeError, ValueError): print("Erreur de Valeur/Type") except SyntaxError: print("Il y a une erreur de syntaxe") except ZeroDivisionError: print("Il y a une division par zéro") except: print("Quelque chose n'a pas fonctionné, mais quoi?") else: fini = True print('Le résultat est:',result) |
Et voici un exemple d’utilisation de la procédure calcul :
|
1 2 3 4 5 6 7 8 9 10 11 |
>>> calcul() Entrez une expression numérique: [1,2,3] Erreur de Valeur/Type Entrez une expression numérique: 1** Il y a une erreur de syntaxe Entrez une expression numérique: 1/0 Il y a une division par zéro Entrez une expression numérique: sqrt(5) Quelque chose n'a pas fonctionné, mais quoi? Entrez une expression numérique: 1/2+2/3 Le résultat est: 1.1666666666666665 |
Les erreurs sont souvent subies (puis traitées), mais elles peuvent aussi être provoquées (on dit alors levées).
Cela peut correspondre à la réalisation d’une situation très particulière ("exceptionnelle") et l’utilisation de clauses try... except... peut constituer une bonne alternative aux clauses if... then....
Dans le petit programme suivant, on part à la recherche d’un élément cible dans une liste. Si l’élément cible est trouvé, on lève Exception (ce qui est la classe d’exception la plus générale) et on répond par le message "Trouvé" (le parcours de la liste est alors interrompu, bien sûr). Sinon (et il faut pour cela aller jusqu’au bout de la liste), et donc s’il n’y a pas d’erreur, la clause else affiche le message "Non trouvé".
|
1 2 3 4 5 6 |
def cherche(cible,liste): try: for elt in liste: if elt == cible: raise Exception except: print("Trouvé") else: print("Non trouvé") |
Voici un exemple d’utilisation de la fonction cherche :
|
1 2 3 4 |
>>> cherche(8,[2,6,1,9,8,3,4,0,7]) Trouvé >>> cherche(5,[2,6,1,9,8,3,4,0,7]) Non trouvé |