• Aucun résultat trouvé

Exceptions du langage

Dans le document Python Python (Page 177-182)

Python propose une liste de classes d’exception directement accessibles sans directive d’importation, et utilisées par le langage. Les classes sont organisées en deux niveaux :

• La première couche contient un ensemble de classes de base qui ne sont jamais directement appelées.

>>> 7 / 0

Traceback (most recent call last):

File "<stdin>", line 1, in ?

ZeroDivisionError: integer division or modulo by zero

>>> class BrokenCode:

... pass ...

>>> def func():

... raise BrokenCode() ...

>>> func()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

File "<stdin>", line 2, in func

__main__.BrokenCode: <__main__.BrokenCode instance at 0x84300>

BONÀSAVOIR Exceptions de type string

Le support des exceptions de type string (comme raise 'erreur !') a été supprimé depuis Python 2.6.

• La deuxième couche représente soit des classes qui dérivent d’une des classes de base et qui sont utilisables, soit des classes concrètes.

Classes d’exceptions de base

Exception

Exception est la classe de base de toutes les exceptions. Son constructeur peut être appelé avec un ou plusieurs paramètres libres qui sont conservés dans l’attribut args. Lorsque l’exception est levée, l’interpréteur affiche le type d’exception, suivi de la chaîne de caractères obtenue par str(exception), soit un appel à

exception.__str__(). La méthode __str__() de la classe Exception renvoie une chaîne de caractères représentant args.

StandardError

Dérivée d’Exception, StandardError est la classe de base pour la quasi-totalité des classes d’exceptions.

ArithmeticError

Dérivée de StandardError, ArithmeticError est la classe de base pour les exceptions relatives aux erreurs arithmétiques, soit la division par zéro (ZeroDivisionError), un dépassement de capacité (OverflowError), une erreur de calcul en virgule flottante (FloatingPointError).

LookupError

Dérivée de StandardError, LookupError est la classe de base pour les exceptions relatives aux erreurs d’index ou de clé, lorsqu’un appel à une clé inexistante est faite sur un mapping ou sur un index hors limite sur une séquence.

EnvironmentError

Dérivée de StandardError, EnvironmentError est la classe de base pour les erreurs système, comme des erreurs de lecture ou d’écriture (IOError) ou des erreurs provo-quées lors d’appels à des API système (OSError).

Le système d’exploitation possède une liste d’erreurs standardisée, représentée par des entiers que l’on peut retrouver dans le module errno. Lorsqu’un programme provoque une erreur système, il peut lever une exception EnvironmentError

cons-À RETENIR Différence entre classes d’exception abstraites et concrètes

Cette distinction entre classes d’exception abstraites et concrètes est purement symbolique et il reste techniquement tout à fait possible de lever des exceptions avec les classes de base.

truite avec le couple (errno, message). L’instance présentera alors deux attributs

errno et strerror, utilisés par __str__(). Levée d’une OSError

Il est possible enfin d’instancier l’exception avec un troisième paramètre représentant un nom de fichier. Ce troisième paramètre est souvent utile pour IOError.

UnicodeError

Classe de base pour les erreurs relatives aux conversions entre type unicode et type

string et aux problèmes de traduction de caractères (par appel de translate()).

Une erreur de conversion d’unicode vers string est une erreur d’encodage (UnicodeEncodeError) et de string vers unicode une erreur de décodage (UnicodeDecodeError). Cette distinction a été introduite dans la version 2.3.

Warning

Classe de base pour toutes les exceptions de type avertissement.

Classes concrètes

Les classes d’exceptions concrètes sont présentées dans le chapitre suivant.

try..except..else

Lorsqu’une exception est levée, le programme est interrompu et l’interpréteur remonte en sens inverse toutes les couches de code précédemment traversées, à la manière d’une bulle d’air qui remonte dans l’eau. Arrivée à la surface, l’exception est affichée et le programme s’arrête.

Il est cependant possible de stopper cette remontée en interceptant l’erreur, avec la directive try..except. Tout le code contenu ou appelé dans le bloc délimité par try est surveillé par l’interpréteur. En cas de levée d’exception, l’exécution du bloc s’arrête et l’interpréteur exécute le code contenu dans le bloc except avant de continuer le programme normalement.

Si le code ne lève pas d’exception le programme continue et ignore le bloc contenu dans except.

>>> import errno

>>> error = OSError(errno.ECONNREFUSED, 'Connection refused')

>>> raise error

Traceback (most recent call last):

File "<stdin>", line 1, in ?

OSError: [Errno 111] Connection refused

Il reste en outre possible d’appeler à nouveau une directive raise dans le bloc except (principe du reraise).

Utilisation de try..except

Cette écriture a cependant un inconvénient majeur : il est impossible de savoir quel type d’erreur est survenue dans le bloc. Cette protection aveugle peut entraîner des effets de bords dans la suite du programme en masquant silencieusement toutes les erreurs.

Pour éviter ce problème, il est possible de préciser quelle classe d’exception est gérée par la directive except. Dans ce cas, le bloc sera ignoré si l’exception levée n’est pas du type indiqué.

Typage de l’exception

En outre, il est possible d’associer plusieurs exceptions à un bloc except et d’enchaîner plusieurs blocs except.

Série d’except

except peut aussi prendre un nom de variable en deuxième paramètre qui reçoit l’instance de l’exception levée.

>>> try:

... print(2 / 0) ... except:

... print('une erreur est survenue') ...

une erreur est survenue

>>> try:

... print(2 / 0)

... except ZeroDivisionError:

... print('+infini') ...

+infini

>>> try:

... print(a)

... except ZeroDivisionError:

... print('division par zéro')

... except (AttributeError, NameError):

... print('element non défini') ...

element non défini

Enfin, un bloc else peut être ajouté à la fin du bloc try..except, et ne sera exécuté que s’il n’y a eu aucune erreur.

try..finally

La directive try..finally permet de s’assurer qu’un bloc de code est toujours exécuté : le bloc contenu dans la directive try peut lever une exception, ou même exécuter une directive return ou break, le bloc finally sera toujours exécuté.

Lecture d’un fichier

Dans cet exemple, la directive finally permet de s’assurer que le mot « fini » sera écrit dans le fichier, quoi qu’il advienne dans some_code().

try..except..finally

Pour simplifier le code, il est aussi possible d’unifier les directives except et finally imbriquées depuis Python 2.5.1.

Unification

>>> try:

... print(2 / 0)

... except ZeroDivisionError, error:

... print('Erreur: %s' % str(error)) ...

Erreur: integer division or modulo by zero

>>> with open('zipfile.py', 'w') as file_

... try:

... some_code() ... finally:

... file_.write('fini') ...

À RETENIR Débogage d’un programme Python

Pour déboguer un programme Python, il convient d’utiliser le module pdb, présenté au chapitre 9.

>>> try: # avant 2.5.1 ... try:

... print('le code') ... except:

... print("l'erreur")

Dans le document Python Python (Page 177-182)