Exceptions et assertions
Temps de lecture10 minEn bref
Résumé de l’article
Dans ce cours, nous introduisons les exceptions, qui indiquent des erreurs détectées pendant l’exécution du programme.
Nous détaillons également les assertions, qui permettent de faire des vérifications à un certain point du programme. Elles sont très pratiques pour le développement, car elles permettent de lever des erreurs quand quelque chose ne va pas.
Points clés à retenir
-
Les exceptions sont des erreurs qui surviennent pendant l’exécution du programme, comme des saisies utilisateur invalides ou des fichiers manquants.
-
Les exceptions peuvent être capturées et gérées par le programme.
-
Le bloc
try-exceptest utilisé pour capturer et gérer les exceptions en Python. -
La clause
finallyest utilisée pour définir des actions de nettoyage qui doivent être exécutées dans toutes les circonstances. -
La clause
raisepermet de lever (i.e. générer une exception). -
Les assertions sont faites pour valider et appliquer les conditions attendues dans le code pendant l’exécution.
-
Les assertions échouées fournissent un retour immédiat, aidant les développeurs à identifier et corriger rapidement les problèmes.
-
L’utilisation cohérente des assertions applique des contraintes, conduisant à un logiciel plus robuste et fiable.
-
Les assertions peuvent être facilement activées/désactivées pour la production.
Contenu de l’article
1 — Exceptions
1.1 — Qu’est-ce qu’une exception ?
Un code peut être syntaxiquement et sémantiquement correct mais voir son exécution abortée brutalement à cause d’une erreur dite d’exécution. Voici quelques exemples de tels scénarios :
- Un utilisateur saisit des données invalides.
- Un fichier est manquant ou inaccessible.
- Une connexion réseau est perdue.
Les exceptions sont utilisées pour traiter ces erreurs.
Une exception est un événement qui se produit pendant l’exécution d’un programme, qui perturbe le flux normal des instructions. Mais les exceptions ne sont pas nécessairement fatales, elles peuvent être gérées par le programme.
Cependant, quand une exception n’est pas gérée par les programmes, cela résulte en un message d’erreur comme celui montré ci-dessous :
Exécuter le code précédent avec b = 0 lèvera une ZeroDivisionError en Python.
La dernière ligne du message d’erreur indique ce qui s’est passé.
Les exceptions viennent en différents types, et le type est affiché comme partie du message (ZeroDivisionError).
La chaîne affichée comme type d’exception est le nom de l’exception intégrée qui s’est produite.
Information
Les programmes peuvent définir leurs propres types d’exception en créant une nouvelle classe d’exception (qui devrait être dérivée de la classe Exception), mais nous nous focaliserons sur les types existants dans cette session.
1.2 — Gestion des exceptions
1.2.1 — Le bloc try-except
Il est possible d’écrire des programmes qui gèrent des exceptions sélectionnées, c’est-à-dire, qui détectent quand une exception se produit, et la capturent pour faire quelque chose et empêcher le programme de planter.
Pour ce faire, nous pouvons utiliser un bloc try-except pour capturer et gérer l’exception.
La syntaxe du bloc try-except est la suivante :
L’instruction try fonctionne comme suit :
- D’abord, la clause
try(la ou les instruction(s) entre les mots-cléstryetexcept) est exécutée. - Voici ce qui peut arriver ensuite :
- Si aucune exception ne se produit, la clause
exceptest ignorée, et l’exécution de la clausetryest terminée. - Si une exception se produit pendant l’exécution de la clause
try(par exemple, à la ligne 42), le reste de la clause (lignes 43 et au-delà) est ignoré. Ensuite, si le type de l’exception levée correspond à l’exception nommée après le mot-cléexcept(<exception type>dans le code ci-dessus), la clauseexceptest exécutée, et puis l’exécution continue après le bloctry-except. - Si une exception se produit qui ne correspond pas à l’exception nommée dans la clause except, elle est transmise aux instructions
tryexternes (s’il y en a). Si aucun gestionnaire n’est trouvé, c’est une exception non gérée et l’exécution s’arrête avec un message d’erreur.
- Si aucune exception ne se produit, la clause
L’exemple suivant demande à l’utilisateur une saisie jusqu’à ce qu’un entier valide ait été saisi, mais permet à l’utilisateur d’interrompre le programme (en utilisant Control-C).
Une instruction try peut avoir plus d’une clause except, pour spécifier des gestionnaires pour différentes exceptions.
Au plus un gestionnaire sera exécuté.
Une clause except peut nommer plusieurs exceptions comme un tuple entre parenthèses, par exemple :
L’instruction pass est utilisée comme espace réservé pour du code futur.
Quand l’instruction pass est exécutée, rien ne se passe (c’est une commande pour “ne rien faire”), mais vous évitez d’obtenir une erreur quand du code vide n’est pas autorisé.
Le code vide n’est pas autorisé dans les boucles, les définitions de fonctions, les définitions de classes, ou dans les instructions if.
Information
Comme toutes les exceptions Python sont dérivées d’une classe de base appelée Exception, vous pouvez capturer toute erreur qui se produit pendant le bloc try en écrivant :
Ou, de manière équivalente :
Enfin, si vous voulez plus d’informations sur l’exception que vous avez capturée, vous pouvez utiliser la bibliothèque traceback, et obtenir l’exception dans une variable (e dans le code ci-dessous) :
1.2.2 — Définir des actions de nettoyage
L’instruction try a une autre clause optionnelle qui est destinée à définir des actions de nettoyage qui doivent être exécutées dans toutes les circonstances.
Si une clause finally est présente, la clause finally s’exécutera comme dernière tâche avant que l’instruction try ne se termine.
Par exemple :
Information
La clause finally est exécutée qu’une exception soit levée ou non dans la clause try.
1.3 — Lever des exceptions
Les exceptions sont levées quand une erreur se produit.
Mais il est aussi possible pour un programmeur de forcer une exception à se produire avec le mot-clé raise.
L’argument de raise indique l’exception à lever.
Cela doit être soit une instance d’exception soit une classe d’exception.
Par exemple :
Dans l’exemple ci-dessus, la fonction euclidean_division lève une ZeroDivisionError en Python si le diviseur b est 0.
Ici, le même type d’erreur est levé mais le message diffère.
Cela montre principalement comment lever une exception.
Nous pourrions aller un peu plus loin et définir notre propre classe étendant Exception et la lever, au lieu de juste personnaliser le message d’erreur.
Avec cela, nous pouvons ajouter des propriétés à l’objet exception créé et les utiliser dans le bloc except.
2 — Assertions
Les assertions sont un outil crucial en développement logiciel utilisé pour valider les hypothèses faites dans le code. Elles sont des types spécifiques d’exceptions, faites à des fins de développement. Les assertions vérifient si des conditions spécifiques sont vraies pendant l’exécution, aidant à détecter les bugs et erreurs logiques au plus tôt.
Quand une assertion échoue, elle fournit un retour immédiat, aidant au débogage rapide. En appliquant des contraintes et des comportements attendus, les assertions contribuent à créer du code plus fiable et maintenable.
2.1 — Qu’est-ce qu’une assertion ?
Les assertions nous donnent un moyen de rendre nos hypothèses explicites dans notre code. Elles sont utilisées pour vérifier que l’état du programme est comme attendu à un point donné dans le code. Si l’assertion échoue, une exception est levée, et le programme s’arrête. Donc, le mécanisme d’assertion est utilisé pour vérifier les conditions pendant l’exécution du code.
La plupart du temps, cela ne nécessite aucune dépendance supplémentaire.
En Python, une assertion est ajoutée en utilisant le mot réservé assert, suivi par la condition à vérifier, et un message optionnel à afficher si l’assertion échoue : assert condition, message.
Considérons la euclidean_division vue plus tôt.
Dans ce code, nous avons une hypothèse que b != 0.
Par conséquent, une assertion peut être plus adaptée qu’une exception :
Les assertions peuvent être utilisées pour enrichir le code en vérifiant les invariants de code et ainsi être vues comme une forme de documentation : elles peuvent décrire l’état que le code s’attend à trouver avant de s’exécuter.
Cependant, les assertions sont seulement utilisées dans la phase de développement et sont rendues silencieuses en production.
Par conséquent, en production, la vérification que b != 0 ci-dessus n’est pas faite.
Il est ainsi supposé que le programme ne devrait jamais appeler la fonction avec ce cas problématique.
Information
Ceci est fait pour accélérer le code et éviter les vérifications inutiles.
Cependant, si vous sentez que l’erreur peut encore arriver pendant la production, une exception peut encore être plus adaptée.
C’est particulièrement le cas quand vous interagissez avec un utilisateur qui pourrait définir b = 0.
Comme les assertions peuvent être désactivées, vous devriez faire attention aux points suivants :
-
Les assertions ne devraient pas avoir d’effets de bord (elles ne devraient pas modifier l’état du programme, mais seulement le vérifier) – Par exemple, vous ne devriez pas utiliser d’assertion pour ouvrir un fichier, mettre à jour une structure de données, etc.
-
Les assertions ne devraient pas être utilisées pour vérifier des conditions qui peuvent être causées par des facteurs externes (par exemple, saisie utilisateur, réseau, etc.) – Par exemple, vous ne devriez pas utiliser d’assertions pour vérifier si un fichier existe.
-
Les assertions ne sont pas un substitut à la gestion d’erreurs, la validation d’entrée, les tests, la documentation, etc.
-
Quand vous utilisez des assertions qui nécessitent un temps d’exécution assez élevé, assurez-vous que les calculs sont faits dans la condition
assert. En effet, si vous calculez le résultat avant, le stockez dans une variable, et puis vérifiez la variable dans l’assert, le calcul sera encore fait lors de la désactivation des assertions. Pour de telles vérifications complexes, il peut ainsi être une bonne idée de définir des fonctions, et les appeler dans l’assert. Par exemple, dans le code suivant, la fonctionis_sortedest appelée dans l’assert:
Pour aller plus loin
Vous pouvez consulter ces deux ressources pour distinguer les propriétés attendues d’un code en mode développement et production :
Pour aller encore plus loin
Il semble que cette section soit vide !
Y a-t-il quelque chose que vous auriez aimé voir ici ? Faites-le nous savoir sur le serveur Discord ! Peut-être que nous pouvons l’ajouter rapidement. Sinon, cela nous aidera à améliorer le cours pour l’année prochaine !