Python : exceptions
1 / 35
Plan
1 Introduction
2 try ... except
3 Message par défaut de l’exception
4 traceback
5 else
6 finally
2 / 35
Plan
7 Multi except
8 Union des except
9 raise
10 assert
11 Exceptions personnalisées
12 Exceptions paramétrées
13 Hiérarchie de classes d’exception
3 / 35
Introduction
Python
Une exception ?
C’est une erreur qui se produit pendant l’exécution de notre
programme
Une exception dans un programme implique généralement son
arrêt d’exécution
4 / 35
Introduction
Considérons la fonction suivante
def division (a: int, b: int) -> int:
return a / b
5 / 35
Introduction
Considérons la fonction suivante
def division (a: int, b: int) -> int:
return a / b
Appeler la fonction avec une valeur pour le deuxième paramètre égal à
zéro déclenche une exception
print(division (2, 0))
print('fin')
# affiche ZeroDivisionError: division by zero
5 / 35
Introduction
Considérons la fonction suivante
def division (a: int, b: int) -> int:
return a / b
Appeler la fonction avec une valeur pour le deuxième paramètre égal à
zéro déclenche une exception
print(division (2, 0))
print('fin')
# affiche ZeroDivisionError: division by zero
Remarque
Le message fin n’a pas été affiché.
5 / 35
Introduction
Python
Comment faire pour poursuivre l’exécution ?
H I ©
EL
Repérer les blocs pouvant générer une exception
U
O
LM
Capturer l’exception correspondante
r e f E
Afficher un message relatif à cette exception
ch
©A
Continuer l’exécution
6 / 35
Introduction
Python
Comment faire pour capturer une exception ?
Utiliser un bloc try: ... except: ... H I ©
U EL
O
Le try pour entourer une instruction susceptible de déclencher
une exception
f E LM
Le except pour r e
chcapturer l’exception et afficher un message qui
© A
lui correspond
7 / 35
try ... except
Python
Utilisons le bloc try except pour capturer l’exception et
continuer l’exécution
try:
H I ©
print(division (2, 0))
U EL
except: O
E
print('division par zéro')
f LM
print('fin')
ch r e
©A
# affiche division par zéro
# affiche fin
8 / 35
try ... except
Python
On peut aussi préciser le type de l’exception
try:
H I ©
EL
print(division (2, 0))
except ZeroDivisionError:
O U
print('division par zéro')
print('fin') f E LM
ch r e
©A
# affiche division par zéro
# affiche fin
9 / 35
Message par défaut de l’exception
Python
Et si on voulait récupérer et afficher le message par défaut de
l’exception
try:
H I ©
print(division (2, 0))
UEL
except ZeroDivisionError as e: O
print(e)
f E LM
print('fin')
ch r e
©A
# affiche division by zero
# affiche fin
10 / 35
traceback
Python
Pour avoir une description plus détaillée, on utilise traceback
import traceback
def division (a: int, b: int) -> int:
try:
return a / b
H I ©
print(division (2, 0))
except ZeroDivisionError as e:
U EL
O
LM
traceback.print_exc()
print('fin')
r e f E
# affiche
ch
©A
# Traceback (most recent call last):
# File "C:/Users/x/cours-exception/[Link]", line 7, in <module>
# print(division (2, 0))
# File "C:/Users/x/cours-exception/[Link]", line 5, in division
# return a / b
# ZeroDivisionError: division by zero
# fin
11 / 35
else
Python
Pour exécuter une suite d’instructions si aucune exception n’a
été levée
try:
print(division (4, 2))
H I ©
except ZeroDivisionError as e:
U EL
O
LM
print(e)
else:
r e f E
ch
print('calcul terminé avec succès')
©A
print('fin')
# affiche calcul terminé avec succès
# affiche fin
12 / 35
finally
Python
Pour exécuter une suite d’instructions qu’une exception soit levée ou non
try:
print(division (4, 0))
except ZeroDivisionError as e:
print(e)
finally:
print('tout le temps exécuté')
print('fin')
# affiche tout le temps exécuté
# affiche fin
13 / 35
finally
Python
Pour exécuter une suite d’instructions qu’une exception soit levée ou non
try:
print(division (4, 0))
except ZeroDivisionError as e:
print(e)
finally:
print('tout le temps exécuté')
print('fin')
# affiche tout le temps exécuté
# affiche fin
Retestez avec les valeurs 4 et 2 pour les paramètres de la fonction division et
vérifiez que le le message tout le temps exécuté est toujours affiché.
13 / 35
Multi except
Python
Et si on appelle la fonction avec un type autre que int, une
exception sera lancée (et non capturée, le message fin ne sera
donc pas affiché)
try:
print(division (2, 'a'))
except ZeroDivisionError:
print('division par zéro')
print('fin')
# affiche TypeError: unsupported operand type(s) for
/: 'int' and 'str'
14 / 35
Multi except
Python
On peut utiliser plusieurs fois le bloc except
try:
print(division (2, 0))
except ZeroDivisionError:
H I ©
print('division par zéro')
U EL
O
except TypeError:
f E LM
r e
print('Les deux paramètres doivent être de type
ch
A
entier')
©
print('fin')
# affiche division par zéro
# affiche fin
15 / 35
Multi except
Python
On peut aussi définir un bloc except général
try:
print(division (4, 2))
except ZeroDivisionError:
H I ©
EL
print('division par zéro')
O U
LM
except TypeError:
r e f E
print('Les deux paramètres doivent être de type entier')
except:
ch
©A
print('erreur inconnue')
print('fin')
# affiche 2.0
# affiche fin
16 / 35
Union des except
Python
On peut fusionner les blocs except
try:
print(division (2, 'a'))
H I ©
EL
except (ZeroDivisionError, TypeError):
print('Problème avec les paramètres')
O U
except:
f E LM
r e
print('erreur inconnue')
ch
print('fin')
©A
# affiche Problème avec les paramètres
# affiche fin
17 / 35
raise
Python
Malgré le typage des paramètres de la fonction, les types numériques (float
par exemple) peuvent passer
try:
print(division (4.0, 2))
H I ©
except (ZeroDivisionError, TypeError):
U EL
O
print('Problème avec les paramètres')
f E LM
except:
ch r e
print('erreur inconnue')
print('fin') ©A
# affiche 2.0
# affiche fin
18 / 35
raise
Python
On peut utiliser raise pour lancer une exception si le type ne correspond pas
def division (a: int, b: int) -> int:
if type(a) == int and type(b) == int:
return a / b
else:
H I
raise Exception("Cette fonction n'accepte que les ©
entiers")
U EL
O
try:
print(division (4.0, 2))
f E LM
ch r e
except (ZeroDivisionError, TypeError):
©A
print('Problème avec les paramètres')
except Exception as e:
print(e)
print('fin')
# affiche Cette fonction n'accepte que les entiers
# affiche fin
19 / 35
assert
Python
Une exception peut aussi lancée en utilisant assert
def division (a: int, b: int) -> int:
assert type(a) == int and type(b) == int, Exception("Cette
fonction n'accepte que les entiers")
return a / b
H I ©
U EL
try:
O
print(division (4.0, 2))
f E LM
except (ZeroDivisionError, TypeError):
ch r e
print('Problème avec les paramètres')
©A
except Exception as e:
print(e)
print('fin')
# affiche Cette fonction n'accepte que les entiers
# affiche fin
20 / 35
Exceptions personnalisées
Python
On a utilisé (ou vu) des exceptions prédéfinies
ZeroDivisionError
ValueError
21 / 35
Exceptions personnalisées
Python
On a utilisé (ou vu) des exceptions prédéfinies
ZeroDivisionError
ValueError
On peut aussi définir nos exceptions personnalisées
21 / 35
Exceptions personnalisées
Python
Considérons la classe Adresse suivante
class Adresse:
H I ©
EL
def __init__(self, rue: str = '', ville: str = '',
U
code_postal: str = ''):
O
self.__rue = rue
f E
self.__ville = ville LM
ch r e
self.__code_postal = code_postal
# + ©A
getters + setters + __str__
22 / 35
Exceptions personnalisées
Python
Supposons que
code postal doit contenir exactement 5 chiffres
23 / 35
Exceptions personnalisées
Python
Supposons que
code postal doit contenir exactement 5 chiffres
Démarche à faire
Créer notre propre exception (qui doit étendre la classe Exception)
Dans le constructeur de Adresse, on lance une exception si code postal ne
contient pas 5 chiffres.
23 / 35
Exceptions personnalisées
Python
Créons l’exception CodePostalError
class CodePostalError(Exception):
def __init__(self):
super().__init__("Le code postal doit contenir 5 caractères")
24 / 35
Exceptions personnalisées
Python
Modifions le constructeur de la classe Adresse
from code_postal_error import CodePostalError
class Adresse:
H I ©
UEL
O
def __init__(self, rue: str = '', ville: str = '',
code_postal: str = ''):
f E LM
self.__rue = rue
ch r e
self.__ville = ville
©A
if len(code_postal) != 5:
raise CodePostalError()
self.__code_postal = code_postal
# + getters + setters + __str__
25 / 35
Exceptions personnalisées
Python
Testons tout cela dans le main
from adresse import Adresse
try:
adresse = Adresse("paradis", "Marseille", "1301")
except Exception as e:
print(e)
print("fin")
26 / 35
Exceptions personnalisées
Python
Testons tout cela dans le main
from adresse import Adresse
try:
adresse = Adresse("paradis", "Marseille", "1301")
except Exception as e:
print(e)
print("fin")
Le message affiché est :
Le code postal doit contenir exactement 5 chiffres
fin
26 / 35
Exceptions paramétrées
Python
Question
Comment faire si on veut afficher les valeurs qui ont déclenché
l’exception dans le message ?
27 / 35
Exceptions paramétrées
Python
Modifions la première exception CodePostalError
class CodePostalError(Exception):
def __init__(self, value):
super().__init__(f"Le code postal {value} doit contenir
exactement 5 caractères")
28 / 35
Exceptions paramétrées
Python
Modifions le constructeur de la classe Adresse
from code_postal_error import CodePostalError
class Adresse:
H I ©
UEL
O
def __init__(self, rue: str = '', ville: str = '',
code_postal: str = ''):
f E LM
self.__rue = rue
ch r e
self.__ville = ville
©A
if len(code_postal) != 5:
raise CodePostalError(code_postal)
self.__code_postal = code_postal
# getters + setters + __str__
29 / 35
Exceptions paramétrées
Python
Testons tout cela dans le main
from adresse import Adresse
try:
adresse = Adresse("paradis", "Marseille", "1301")
except Exception as e:
print(e)
print("fin")
30 / 35
Exceptions paramétrées
Python
Testons tout cela dans le main
from adresse import Adresse
try:
adresse = Adresse("paradis", "Marseille", "1301")
except Exception as e:
print(e)
print("fin")
Le message affiché est :
Le code postal 1301 doit contenir exactement 5 chiffres
fin
30 / 35
Exceptions paramétrées
Python
Exercice
Nous voulons modifier l’exception précédente et la renommer en
AdresseError pour qu’elle lève une exception si le code postal ne
contient pas 5 caractère ou si la rue n’est pas entièrement en
majuscule. L’exception doit rester paramétrée
31 / 35
Exceptions paramétrées
Python
Quelques conventions PEP 8 sur les exceptions
Une exception est une classe donc elle doit respecter le Pascal case
Le nom d’une exception doit se terminer par le mot Error
32 / 35
Hiérarchie de classes d’exception
Hiérarchie des classes d’exception
BaseException
StopIteration SystemExit Exception KeyboardInterrupt
NameError TypeError ArithmeticError ValueError
OverFlowError ZeroDivisionError FloatingPointError
33 / 35
Hiérarchie de classes d’exception
Python
BaseException
La classe BaseException est au sommet de la hiérarchie des exceptions en Python.
Elle n’est pas destinée à être directement levée par les développeurs intégrées.
Elle est plutôt utilisée comme classe mère pour toutes les autres exceptions intégrées.
34 / 35
Hiérarchie de classes d’exception
Python
BaseException
La classe BaseException est au sommet de la hiérarchie des exceptions en Python.
Elle n’est pas destinée à être directement levée par les développeurs intégrées.
Elle est plutôt utilisée comme classe mère pour toutes les autres exceptions intégrées.
Exception
Généralement utilisée pour définir les exceptions personnalisées
Classe de base pour toutes les exceptions intégrées, à l’exception de SystemExit,
KeyboardInterrupt, GeneratorExit et StopIteration.
34 / 35
Hiérarchie de classes d’exception
Python
Exceptions intégrées ou prédéfinies (Built-in exceptions)
Elles sont des types d’exceptions qui sont incluses dans le langage Python par défaut.
Elles sont disponibles pour être utilisées dans vos programmes sans nécessiter
d’importation supplémentaire.
H I ©
Exemples
UEL
O
LM
TypeError : Levée lorsque l’opération ou la fonction est appliquée à un objet d’un
type inapproprié.
r e f E
ValueError : Levée lorsque la fonction reçoit un argument d’une valeur incorrecte.
ch
©A
NameError : Levée lorsque le nom d’une variable ou d’une fonction n’est pas trouvé
dans l’espace de noms local ou global.
ZeroDivisionError : Levée lorsque la division ou le modulo par zéro est tenté.
ImportError : Levée lorsqu’un import échoue
IndentationError : Levée lorsque l’indentation est incorrect.
...
35 / 35