Aller au contenu

Programmation Python/Exceptions

Un livre de Wikilivres.

Une exception est un signal d'erreur associé à un type de données donnant des informations sur l'erreur. En Python, il s'agit d'un objet.

La capture des exceptions permet l'exécution d'instructions par un interpréteur ou par le processeur (langage compilé) lorsqu'une erreur est détectée au cours de l'exécution d'un programme. En règle générale, lorsque l'erreur n'est pas capturée, l'exécution du programme est alors interrompue, et un message d'erreur plus ou moins explicite est affiché.

Exemple en Python 2 :

>>> print 55/0
ZeroDivisionError: integer division or modulo

Exemple en Python 3 :

>>> print(55/0)
ZeroDivisionError: division by zero
 D'autres informations complémentaires sont affichées, qui indiquent notamment à quel endroit du script l'erreur a été détectée, mais nous ne les reproduisons pas ici.

Le message d'erreur proprement dit comporte deux parties séparées par un double point : d'abord le type d'erreur, et ensuite une information spécifique de cette erreur.

Dans de nombreux cas, il est possible de prévoir à l'avance certaines des erreurs qui risquent de se produire à tel ou tel endroit du programme, et d'inclure à cet endroit des instructions particulières, qui seront activées seulement si ces erreurs se produisent. Dans les langages de niveau élevé comme Python, il est également possible d'associer un mécanisme de surveillance à tout un ensemble d'instructions, et donc de simplifier le traitement des erreurs qui peuvent se produire dans n'importe laquelle de ces instructions.

Un mécanisme de ce type s'appelle en général mécanisme de traitement des exceptions. Celui de Python utilise l'ensemble d'instructions try - except – else, qui permettent d'intercepter une erreur et d'exécuter une portion de script spécifique de cette erreur. Il fonctionne comme suit :

Le bloc d'instructions qui suit directement une instruction try est exécuté par Python sous réserve. Si une erreur survient pendant l'exécution de l'une de ces instructions, alors Python annule cette instruction fautive et exécute à sa place le code inclus dans le bloc qui suit l'instruction except. Si aucune erreur ne s'est produite dans les instructions qui suivent try, alors c'est le bloc qui suit l'instruction else qui est exécuté (si cette instruction est présente). Dans tous les cas, l'exécution du programme peut se poursuivre ensuite avec les instructions ultérieures.

Considérons par exemple un script qui demande à l'utilisateur d'entrer un nom de fichier, lequel fichier étant destiné à être ouvert en lecture. Si le fichier n'existe pas, nous ne voulons pas que le programme se « plante ». Nous voulons qu'un avertissement soit affiché, et éventuellement que l'utilisateur puisse essayer d'entrer un autre nom.


try:
	# Code pouvant générer une exception
except MonException:
	# Code en cas d'exception
else:
	# Code en cas de non exception
finally:
	#code dans tous les cas
Exemple : Exemple de gestion d'exception


Exemple de gestion d'exception : intercepter une division par zéro.

a = int(input("Veuillez saisir le numérateur : "))
b = int(input("Veuillez saisir le dénominateur : "))

try:
    c = a / b
    print(" Le résultat est :" + c)
except ZeroDivisionError as e:
    print(e.status_code)
    print(str(e))
    print(" Pas de division par zéro SVP")
finally:
    print("Fin du script")

Autre exemple avec un fichier :

filename = raw_input("Veuillez entrer un nom de fichier : ")
try:
    f = open(filename, "r")
except:
    print "Le fichier", filename, "est introuvable"

Logo

C'est une mauvaise pratique de ne pas préciser d’exception pour tout attraper comme ci-dessus. Il faut plutôt utiliser la classe mère de toutes les exceptions : BaseException

Si nous estimons que ce genre de test est susceptible de rendre service à plusieurs endroits d'un programme, nous pouvons aussi l'inclure dans une fonction :

def existe(fname):
    try:
        f = open(fname,'r')
        f.close()
        return 1
    except:
        return 0

filename = raw_input("Veuillez entrer le nom du fichier : ")
if existe(filename):
    print "Ce fichier existe bel et bien."
else:
    print "Le fichier", filename, "est introuvable."

Il est également possible de faire suivre l'instruction "try" de plusieurs blocs "except", chacun d'entre eux traitant un type d'erreur spécifique.

Pour attraper plusieurs exceptions :

try:
    from lib import *
except (ImportError, ModuleNotFoundError) as e:
    from src.lib import *

Lancer une exception

[modifier | modifier le wikicode]

Un programme Python peut lancer une exception lorsqu'il détecte une erreur, en utilisant l'instruction raise :

def construire_table(taille):
    if (taille < 1):
        raise Exception("La taille spécifiée est invalide.")
    # On peut continuer car taille est supérieur ou égal à 1 ...

Testé dans l'interpréteur interactif de Python :

>>> construire_table(1)
>>> construire_table(2)
>>> construire_table(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in construire_table
Exception: La taille spécifiée est invalide.

Créer une exception

[modifier | modifier le wikicode]

Il est possible de définir un nouveau type d'exception pour un type d'erreur spécifique. Pour cela, il faut créer une nouvelle classe dérivant de la classe BaseException ou d'une de ses sous-classes (Exception par exemple).

class InvalidSizeException(Exception):
    def __init__(self, taille):
        Exception.__init__(self, f"Taille invalide : {taille}")

def construire_table(taille):
    if (taille < 1):
        raise InvalidSizeException(taille)
    # On peut continuer car taille est supérieur ou égal à 1 ...

Testé dans l'interpréteur interactif de Python :

>>> construire_table(2)
>>> construire_table(1)
>>> construire_table(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in construire_table
__main__.InvalidSizeException: Taille invalide : 0
>>> construire_table(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in construire_table
__main__.InvalidSizeException: Taille invalide : -1