UKOnline

Gestion d'erreur

La gestion des erreurs est une activité importante lorsque l'on rédige un programme si on le souhaite le plus robuste possible. De manière générale, il existe deux approches pour gérer les erreurs dans un programme.

La première, appelée LBYL (Look Before You Leap), consiste à explicitement vérifier que toutes les préconditions sont bien satisfaites avant d'exécuter un code. C'est, par exemple, l'approche utilisée en C ou en Go.

L'autre approche, appelée EAFP (Easier to Ask for Forgiveness than Permission), et préconisée en Python, consiste à supposer que les hypothèses sont satisfaites et à gérer les éventuelles erreurs avec le mécanisme d'exception, à savoir try-except en Python.

Accès à un dictionnaire

Accéder au contenu d'un dictionnaire se fait essentiellement à partir des clés des paires clé-valeur contenues dans le dictionnaire. Voici deux fonctions qui permettent de compter les fréquences d'apparition des lettres présentes dans un mot :

La première fonction vérifie systématiquement si la lettre est présente ou non comme clé dans le dictionnaire et, si ce n'est pas le cas, rajoute cette clé en lui associant la valeur $0$. On est clairement dans une approche LBYL et ce type de code n'est pas du tout « pythonique ».

La seconde fonction, qui suit l'approche EAFP, est beaucoup plus courante en Python. Elle accède systématiquement à la clé dans le dictionnaire pour incrémenter la valeur associée et, si une exception de type KeyError se produit, rajoute la clé manquante dans le dictionnaire en lui associant la valeur $1$.

Au niveau des performances, le fait d'utiliser un try-except n'est pas pénalisant, les deux fonctions prenant 106 ms pour s'exécuter avec une chaine de caractères aléatoire de cent-mille lettres minuscules. L'approche EAFP sera parfois plus rapide, en fonction de la complexité de la condition du if dans l'approche LBYL.

Expression régulière

Voyons un autre exemple où l'utilisation d'un try-except est bien plus rapide que le test équivalent à l'aide d'un if, car la condition de ce dernier est complexe et prend beaucoup de temps à évaluer.

Voici deux fonctions qui permettent de calculer la somme des nombres entiers se trouvant dans une liste de chaine de caractères (ces nombres entiers, stockés comme des chaines de caractères, pourraient provenir de la lecture d'un fichier texte, par exemple) :

La première fonction vérifie, à l'aide d'une expression régulière, que l'on a bien un nombre entier qui pourra donc être converti sans erreur en un nombre de type int. La seconde fonction fait l'hypothèse que l'on a bien des nombres entiers en convertissant directement les éléments de la liste reçue en paramètre. Si ce n'est pas le cas, la fonction traite la situation exceptionnelle en utilisant le mécanisme d'exception avec un try-except, en capturant une exception de type ValueError.

La seconde fonction est beaucoup plus rapide que la première. En effet, on passe de 250 ms à 67 ms pour calculer la somme des éléments d'une liste de cent-mille nombres représentés par des chaines de caractères, soit une diminution de temps de 73 %.