Lorsqu’on développe un programme, que ce soit en Big Data ou pour tout autre utilisation, il y a toujours un risque que l’on génère des erreurs. Ces erreurs peuvent provenir de l’utilisateur de la solution ou bien de l’exécution du programme lui-même. Pour éliminer ou du moins limiter l’apparition de ces erreurs au niveau de l’interface et pour que ces derniers ne nuisent pas à l’ensemble de l’application, beaucoup de langages ont mis en place la gestion des exceptions, y compris Python.
Dans d’autres langages comme Java par exemple, on identifie la gestion de ces exceptions à l’aide de l’instruction try…catch. Pour la gestion des exceptions en Python, la syntaxe est un peu différente, car on utilise plutôt l’instruction try…except.
Dans ce tutoriel exhaustif, nous allons vous apprendre à gérer les exceptions en Python.
Qu’est-ce qu’une exception en Python ?
Tout d’abord, il faut connaitre ce qu’une erreur signifie en Python. En fait, il existe deux types d’erreurs en Python :
- Les erreurs de syntaxe ;
- Et les exceptions.
Les erreurs de syntaxe sont celles que l’on peut faire lors de l’écriture du programme. Cela peut être l’appel d’une variable non gérée par le programme, un oubli dans l’écriture d’une instruction (« : » non mis, une parenthèse non fermée, etc..) ou l’appel d’un module non déclaré au préalable. Ces erreurs sont corrigibles de suite, car Python les signale avant même l’exécution du programme. En effet, il pointe une petite flèche sur la partie où se situe l’erreur pour que vous puissiez les modifier selon la bonne syntaxe à écrire.
Quant aux exceptions, elles surviennent plutôt à cause d’une exécution invalide à l’intérieur du programme. Cela peut être une erreur venant de l’utilisateur, par exemple la saisie d’une entrée ne correspondant pas à la valeur attendue. Elle peut également venir d’une erreur de programmation, c’est-à-dire d’une manipulation faite par le développeur et qui, lors de l’exécution, entraine une opération non prise en charge par le langage. Les exceptions ne sont levées que lorsqu’elles apparaissent, on ne peut donc pas les détecter au moment de l’élaboration du programme. C’est pour cela qu’il est important de les gérer à l’aide de l’instruction try…except de Python au risque de voir la solution planter.
Comment se présentent les exceptions en Python ?
En Python, les exceptions s’affichent après la tentative d’exécution de l’instruction invalide. Voyons cela avec ce petit exemple :
resultat = 10/0
... print(resultat)
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division by zero
Ici, les trois dernières lignes représentent la trace de l’exception. Elles contiennent le contexte dans lequel l’exception est survenue. Il s’agit là du module concerné et du numéro de la ligne dans laquelle se situe l’erreur. La dernière ligne précise le type d’exception généré. Ici, c’est la division par 0 qui a été déclenchée à l’aide de la classe d’exception ZeroDivisionError. La suite de cette ligne donne les détails concernant l’exception.
Afin que vous puissiez comparer le fonctionnement des exceptions et de try…except en Python à travers les différents langages de programmation, vous pouvez consulter le tutoriel que nous avons publié sur l’utilisation de try…catch en Java.
Il existe plusieurs classes d’exception en Python et nous allons les représenter dans le graphique hiérarchique suivante :
Comme vous le voyez sur ce graphique, toutes les exceptions héritent de la classe BaseException. Et pour ce qui est des exceptions fréquemment rencontrées et celles que nous allons créer nous-mêmes (nous verrons cela en détail dans les prochaines sections), elles sont issues de la classe Exception. Celles illustrées dans l’organigramme sont ce qu’on appelle les exceptions natives. Plus de détails dans la documentation officielle de Python. Cependant, à titre d’information la classe ArithmeticError qui contient les exceptions ZeroDivisionError ou OverflowError, la classe LookupError et la classe OSError sont celles qui sont les plus souvent déclenchées.
La gestion des exceptions avec try…except Python
Entrons maintenant dans le vif du sujet, à savoir la gestion des exceptions avec Python. Toutefois, avant de commencer, nous vous conseillons de prendre en main les bases de ce langage de programmation. Nous avons un article dédié à la programmation Python que vous pouvez consulter pour cela.
Comportement de l’instruction try…except en Python
L’instruction try…except est l’instruction qui permet d’intercepter les exceptions que peuvent générer votre application et d’exécuter d’autres instructions en conséquence.
En pratique, le programme exécute les instructions se trouvant dans la clause try. S’il rencontre une exception, il interrompt l’exécution de celui-ci. Et si cette exception répond à la ou les classes spécifiées dans la clause except, il basculer vers les instructions contenues dans la clause except. À noter que l’on peut spécifier plusieurs exceptions sur la clause except. Il suffit de les séparer avec une virgule (« , »).
Cependant, si l’exception qui survient n’est pas mentionnée dans la clause except, elle est transmise à l’exception du langage lui-même et génère une erreur.
Donc, si nous reprenons notre précédent exemple et que nous y soumettons l’instruction try…except, nous aurons le code suivant :
>>> def exemple():
... try :
... resultat = 10/0
... print(resultat)
... except ZeroDivisionError:
... print("il y a une division par 0")
Le résultat de ce bout de code sera donc l’affichage de « il y a une division par 0 ».
La clause else dans un try…except Python
Il est tout à fait possible de rajouter la clause else après la clause except pour préciser les instructions à exécuter s’il n’y a aucune exception levée.
Pour illustrer cette possibilité, réécrivons notre exemple précédent avec l’utilisation de la clause else et mettons une instruction qui ne déclencherait pas d’exception :
>>> def exemple():
... try :
... resultat = 10/2
... except ZeroDivisionError:
... print("il y a une division par 0")
...
... else :
... print(resultat)
Ici, le résultat sera donc « 5 » puisqu’on a lancé l’instruction dans la clause else.
La clause finally
Il s’agit ici de la dernière clause qui se lance après la gestion d’une exception. Les instructions contenues dans la clause finally se déclencheront peu importe le résultat de l’exécution de l’instruction try…except en Python. Cela permet entre autres de nettoyer le programme avant la poursuite de ce dernier.
Si on le met en pratique avec notre exemple, nous aurons :
>>> def exemple():
... try :
... resultat = 10 * (1/0)
... except ZeroDivisionError:
... print("il y a une division par 0")
...
... else :
... print(resultat)
... finally :
... print("la gestion est terminée")
La phrase « la gestion est terminée » s’affichera juste après l’affichage de « 5 » dans ce cas-ci.
Toutefois, si dans l’une des clauses précédentes, vous enclenchez une instruction break, continue ou return, le contenu de la clause finally se lancera juste avant celles-ci. Et si vous mettez l’une de ces instructions à l’intérieur de la clause finally elle-même, ces instructions seront prises en compte au lieu celles se trouvant dans la clause try.
L’instruction raise
Il faut savoir qu’en Python, on peut lever nous-même une exception. Cette manœuvre s’exécute avec l’instruction raise. Elle peut servir également à propager les exceptions non gérées par la clause except.
Pour ce faire, vous pouvez mentionner l’exception à lever sans mettre un paramètre ou bien spécifier dans le paramètre le message à afficher lors de l’exception. Et pour ce qui est de la propagation des exceptions, il vous suffit de l’écrire sans quoi que ce soit d’autre.
Voyons cela dans un exemple :
>>> def exemple1(a):
... if a == 0 :
... raise ZeroDivisionError("il y a une division par 0")
... try:
... resultat1 = 10/a
... except Exception as exc:
... raise RuntimeError from exc
...
... def exemple2(a):
...
... try:
... resultat2 = 10/a
... except Exception :
... print("il y a une erreur")
... raise
...
... else :
... print(resultat2)
... finally :
... print("la gestion est terminée")
Le mot clé pass
Le mot clé pass est utile lorsque l’on souhaite lever une exception sans pour autant effectuer une instruction précise.
>>> def exemple():
... try:
... resultat2 = 10/0
... except Exception as exc:
... pass
... print("la gestion est terminée")
Ici, le programme affiche directement le message « la gestion est terminée » malgré l’existence d’une exception levée.
Définir ses propres exceptions en Python
Comme nous l’avons mentionné à mainte reprise un peu plus haut, vous pouvez également concevoir vos propres exceptions afin de les adapter au mieux à votre solution. Toutefois, toutes les classes d’exception que vous allez créer doivent hériter de la classe Exception. Il est possible de les faire hériter directement de la classe BaseException, mais cette pratique est déconseillée.
Pour ce faire, vous pouvez procéder comme dans l’exemple qui suit :
class MonException(Exception):
def __init__(self, fonction):
self.fonction = fonction
def __str__(self):
return "Erreur dans {0} ".format(self.message)
def test():
resultat = 10/0
raise MonException("test")
Dans cet exemple, nous avons créé une classe MonException héritant de la classe Exception. À l’intérieur de cette classe, nous avons initialisé la classe en entrant l’expression à affecter en paramètre, il s’agit ici du nom de la fonction qui a généré l’exception. Ensuite, nous avons initialisé le message à afficher si l’exception est levée.
Le résultat de cet exemple sera donc « Erreur dans test ».
Voilà, nous arrivons au terme de ce tutoriel sur la gestion des exceptions en Python. Vous pouvez maintenant appréhender cette fonctionnalité extrêmement utile lors de la programmation d’une solution, surtout si vous souhaitez œuvrer dans le Big Data en tant que Data Engineer.
Afin que vous puissiez en apprendre davantage sur le monde du Big Data ainsi que de la programmation en général, nous vous offrons cette formation sur le langage Scala.