post

Python fr:Exceptions

Contents

Introduction

Les exceptions se produisent quand une situation exceptionnelle arrive dans votre programme. Par exemple, que se passe-t-il quand vous voulez lire un fichier et que ce fichier n’existe pas? Ou quand vous le détruisez par erreur pendant l’exécution du programme? De telles situations sont gérées en utilisant des exceptions.

De la même manière, que se passe-t-il si votre programme a des instructions incorrectes? Cela est géré par Python qui lève (raises) la main et vous dit qu’il y a une erreur.

Erreurs

Considérez un simple appel à la fonction print . Que se passe-t-il si nous faisons une faute de frappe et écrivons print en Print? Notez la lettre majuscule. Dans ce cas, Python lève (raises) un erreur de syntaxe.

   >>> Print('Hello World')
   Traceback (most recent call last):
     File "<pyshell#0>", line 1, in <module>
       Print('Hello World')
   NameError: name 'Print' is not defined
   >>> print('Hello World')
   Hello World

Observez qu’une NameError est levée (raised) et aussi l’emplacement où l’erreur détectée est affichée. C’est ce que fait un error handler pour cette erreur.

Exceptions

Nous allons essayer de saisir des données de l’utilisateur . Tapez ctrl-d et voyez ce qui se passe.

   >>> s = input('Entrez quelque chose --> ')
   Enter something -->
   Traceback (most recent call last):
     File "<pyshell#2>", line 1, in <module>
       s = input('Entrez quelque chose  --> ')
   EOFError: EOF when reading a line

Python lève une erreur appelée EOFError qui veut dire que le symbole end of file (qui est représenté par ctrl-d) a été trouvé alors qu’on ne s’y attendait pas.

Gérer Les Exceptions

Nous pouvons gérer les exceptions avec les instructions try..except . Nous mettons simplement nos instructions habituelles à l’intérieur du bloc try et nos error handlers dans le bloc except.

#!/usr/bin/python
# Nom de fichier: try_except.py

try:
    text = input('Entrez quelque chose --> ')
except EOFError:
    print('Pourquoi m'avez-vous envoyé une fin de fichier?')
except KeyboardInterrupt:
    print('Vous avez annulé l'opération.')
else:
    print('Vous avez saisi {0}'.format(text))

Résultat:

   $ python try_except.py
   Entrez quelque chose -->     # Tapez CTRL-Z
   Pourquoi m'avez-vous envoyé une fin de fichier?

   $ python try_except.py
   Entrez quelque chose -->    # tapez CTRL-C
   Vous avez annulé l'opération.

   $ python try_except.py
   Entrez quelque chose -->  pas d'exception
   Vous avez saisi pas d'exception

Comment cela fonctionne:

Nous mettons toutes les instructions qui peuvent lever des exceptions/erreurs à l’intérieur du bloc try et nous mettons les handlers pour les erreurs/exceptions prévues dans le bloc/clause except . La clause except peut gérer une seule erreur ou exception spécifiée, ou une liste d’erreurs ou d’exceptions entre parenthèses. Si des noms d’erreurs ou d’exceptions ne sont pas indiqués, toutes les erreurs et exceptions seront gérées.

Notez qu’il faut avoir au moins une clause except associée à chaque clause try . Sinon, quel est l’intérêt d’avoir un bloc try?

Si aucune erreur ou exception n’est gérée, alors le handler Python par défaut est appelé qui arrête l’exécution du programme et affiche un message d’erreur. Nous avons déjà vu cela en action au-dessus.

Vous pouvez aussi avoir une clause else associée avec un bloc try..except . La clause else est exécutée si on ne rencontre pas d’exception.

Dans l’exemple suivant, nous verrons comment récupérer l’objet exception afin d’obtenir des informations supplémentaires.

Lever Des Exceptions

Vous pouvez lever (raise) des exceptions avec l’instruction raise en fournissant le nom de l’erreur/exception et l’objet exception qui sera envoyé/thrown.

L’erreur ou exception que vous levez doit être une classe qui doit être dérivée directement ou indirectement de la classe Exception .

#!/usr/bin/python
# Nom de fichier: raising.py

class ShortInputException(Exception):
    '''A user-defined exception class.'''
    def __init__(self, length, atleast):
        Exception.__init__(self)
        self.length = length
        self.atleast = atleast

try:
    text = input('Entrez quelque chose --> ')
    if len(text) < 3:
        raise ShortInputException(len(text), 3)
    # on continue de manière normale ici
except EOFError:
    print('Pourquoi m'avez-vous envoyé une fin de fichier?')
except ShortInputException as ex:
    print('ShortInputException: La saisie avait une longueur de {0}, et on attendait au moins {1}'
          .format(ex.length, ex.atleast))
else:
    print('Pas d'exception levée.')

Résultat:

   $ python raising.py
   Entrez quelque chose -->  a
   ShortInputException: La saisie avait une longueur de 1, et on attendait au moins 3
   $ python raising.py
   Entrez quelque chose -->  abc
   Pas d'exception levée.

Comment cela fonctionne:

Nous créons ici notre propre type d’exception. Ce nouveau type d’exception est appelé ShortInputException. Il possède deux champs – length qui est la longueur saisie, et atleast qui est la longueur minimum attendue par le programme.

Dans la clause except , nous indiquons la classe de l’erreur qui sera stockée en tant que nom de variable pour contenir l’objet erreur/exception correspondant. Cela est comparable aux paramètres et arguments dans un appel de fonction. A l’intérieur de cet clause except particulière, nous utilisons les champs length et atleast de l’objet exception pour afficher le message approprié à l’utilisateur.

Try .. Finally

Supposons, vous lisez un fichier dans votre programme. Comment être certain que l’objet fichier est fermé proprement, qu’une exception ait été levée ou non? Cela peut être fait avec un bloc finally . Notez que vous pouvez utiliser une clause except avec un bloc finally pour le bloc try correspondant. Vous devrez en embarquer un à l’intérieur d’un autre si vous voulez utiliser les deux.

#!/usr/bin/python
# Nom de fichier: finally.py

import time

try:
    f = open('poem.txt')
    while True: # notre idiome habituel pour lire un fichier
        line = f.readline()
        if len(line) == 0:
            break
        print(line, end='')
        time.sleep(2) # Pour être certain que cela dure un peu
except KeyboardInterrupt:
    print('!! Vous avez annulé la lecture à partir du fichier.')
finally:
    f.close()
    print('(Nettoyage: fermeture du fichier)')

Résultat:

   $ python finally.py
   Programming is fun
   When the work is done
   if you wanna make your work also fun:
  !! Vous avez annulé la lecture à partir du fichier.
   (Nettoyage: fermeture du fichier)

Comment cela fonctionne:

Nous faisons la lecture de fichier habituelle, mais nous avons ajouté une attente de 2 secondes après avoir affiché chaque ligne avec la fonction time.sleep afin que le programme s’exécute lentement (Python est naturellement très rapide). Pendant l’exécution du programme, tapez ctrl-c pour interrompre/annuler le programme.

Notez que l’exception KeyboardInterrupt est levée et le programme sort. Cependant, avant la fin du programme, la clause finally est exécutée et l’objet fichier est toujours fermé.

L’Instruction with

Acquérir une ressource dans le bloc try et la relâcher dans le bloc finally est un motif fréquent. Donc, il y a aussi une instruction with qui permet de faire cela de manière propre:

#!/usr/bin/python
# Nom de fichier: using_with.py

with open("poem.txt") as f:
    for line in f:
        print(line, end='')

Comment cela fonctionne:

Le résultat devrait être le même que dans l’exemple précédent. La différence est que nous utilisons la fonction open avec l’instruction with et nous laissons la fermeture du fichier se faire automatiquement avec with open.

Ce qui se passe en arrière-plan est qu’un protocole est utilisé par l’instruction with . Il recherche l’objet retourné par l’instruction open , appelons-le “thefile” dans ce cas.

Il appelle toujours la fonction thefile.__enter__ avant de commencer le bloc de code en dessous et appelle toujours thefile.__exit__ après avoir fini chaque bloc de code.

Donc la méthode __exit__ prendra en charge le code que nous aurions écrit dans un bloc finally . C’est ce qui nous aide à éviter d’utiliser des instructions try..finally de manière répétitive.

Une discussion plus approfondie sur ce sujet est au-delà de l’objectif de ce livre, consultez PEP 343 pour une explication détaillée.

Récapitulatif

Nous avons vu comment utiliser les instructions try..except et try..finally .Nous avons vu comment créer nos propres types d’exceptions et comment lever des exceptions.

Ensuite, nous allons explorer la Librairie Python Standard.


Advertisements