2023-09-11 10:15 Temps de lecture : 15 min

Python Try Except : expliqué avec des exemples

En Python, la structure "try...except" offre un mécanisme robuste pour une gestion élégante des exceptions, empêchant ainsi les arrêts brusques et inattendus de l'exécution de votre programme.

La capacité à gérer ces situations exceptionnelles augmente considérablement la fiabilité de vos applications et minimise le risque de dysfonctionnement. Cet article détaille l'art de la gestion des exceptions, en explorant des cas d'utilisation courants où cette pratique est essentielle. De plus, nous verrons comment il est possible de déclencher volontairement des exceptions.

Comprendre la gestion des exceptions

Les exceptions correspondent à des anomalies critiques ou des erreurs qui se manifestent lors de l'exécution d'un programme. En l'absence d'une gestion appropriée, ces exceptions provoquent l'arrêt brutal du programme. C'est pourquoi la gestion des exceptions est cruciale pour intercepter ces erreurs et garantir le bon fonctionnement de l'application.

Prenons un exemple concret pour illustrer ce concept :

user_input = input("Entrez un nombre: ")
num = int(user_input)
print("Le double de votre nombre est:", num * 2)

À première vue, ce programme semble fonctionner correctement. Il reçoit une entrée utilisateur, la convertit en entier, puis affiche le double de cette valeur.

En exécutant le programme avec une entrée numérique, comme "5", tout se déroule comme prévu.

Cependant, si vous relancez ce même programme, et que vous entrez une chaîne de caractères, par exemple "bonjour", le programme échouera. La chaîne "bonjour" ne peut être convertie en entier, ce qui lève une exception et interrompt l'exécution du programme.

Pourquoi les exceptions sont-elles levées et comment les gérer ?

Les exceptions surviennent souvent parce que, lors du développement, nous divisons nos programmes en fonctions distinctes. Ces fonctions sont ensuite appelées pour exécuter des tâches spécifiques.

Dans l'exemple précédent, nous avons sollicité la fonction `input` pour obtenir une saisie de l'utilisateur, ensuite la fonction `int` pour la convertir en entier, et enfin la fonction `print` pour afficher un résultat.

Cependant, lors de leur exécution, ces fonctions peuvent rencontrer des problèmes qu'elles ne savent pas résoudre. Dans ce cas, elles doivent cesser leur travail et signaler qu'une erreur s'est produite. Cette signalisation se fait par le biais d'une exception.

Le code qui a appelé la fonction doit être en mesure d'intercepter ces exceptions et d'y répondre de manière appropriée. Sans cela, le programme se terminera brutalement après une erreur, comme nous l'avons constaté précédemment.

Les exceptions sont donc un mécanisme de communication permettant à une fonction d'informer le code appelant qu'une anomalie est survenue. La réaction appropriée à cette notification est le fondement même de la gestion des exceptions.

Divers types d'exceptions

Il est important de comprendre que toutes les exceptions ne sont pas identiques. Différents types d'exceptions sont levés pour signaler des erreurs distinctes. Par exemple, une division par zéro entraînera une exception `ZeroDivisionError`. De même, une opération incompatible avec un type de données lèvera une `TypeError`. Une liste exhaustive des types d'exceptions est disponible dans la documentation officielle de Python.

Comment gérer les exceptions

Comme nous l'avons expliqué précédemment, les exceptions sont des signaux d'alarme émis par les fonctions que nous sollicitons. Notre code doit être à l'écoute de ces signaux et réagir de manière appropriée lorsqu'ils sont déclenchés. Pour gérer ces exceptions, nous utilisons la structure "try...except" de Python. Voici la structure de base de cette construction :

try:
    # Code susceptible de provoquer une erreur
except:
    # Code à exécuter en cas d'erreur
finally:
    # Code exécuté dans tous les cas, avec ou sans erreur

Cette construction repose sur trois mots-clés, que nous allons détailler ci-dessous :

try

Le mot-clé "try" marque le début de la structure "try...except". Il délimite un bloc de code qui pourrait éventuellement générer une exception. Il indique à l'interpréteur Python de tenter d'exécuter le code contenu dans ce bloc. Si une exception survient, l'exécution de ce bloc est immédiatement interrompue, et le flux du programme se dirige vers le bloc "except".

except

Le mot-clé "except" définit le bloc de code qui sera exécuté en cas d'exception levée durant l'exécution du bloc "try". Vous pouvez définir plusieurs blocs "except" pour traiter différents types d'exceptions. Nous allons l'illustrer plus loin.

finally

Le mot-clé "finally" est le dernier élément de la construction "try...except". Il définit un bloc de code qui sera exécuté, qu'une exception ait été levée ou non.

Un exemple pratique

Voici un exemple qui illustre l'utilisation des mots-clés précédents pour gérer une exception. Nous allons modifier l'exemple précédent en conséquence :

try:
    user_input = input("Entrez un nombre: ")
    num = int(user_input)
    print("Le double de votre nombre est:", num * 2)
except:
    print("Une erreur est survenue")
finally:
    print("Ce code sera exécuté dans tous les cas")

Si vous exécutez ce code avec une entrée valide, comme "5", vous obtiendrez le résultat suivant :

Par contre, si vous l'exécutez avec "bonjour" comme entrée, vous verrez ceci :

En résumé, si aucune exception n'est levée dans le bloc "try", l'exécution se poursuit vers le bloc "finally". Dans le cas où une exception est levée, le programme exécute d'abord le code du bloc "except" puis celui du bloc "finally".

Vous pouvez également gérer des exceptions de types spécifiques. Par exemple, si vous souhaitez gérer les exceptions `ValueError` et `KeyboardInterrupt` de manière distincte, vous pouvez modifier votre code ainsi :

try:
    user_input = input("Entrez un nombre: ")
    num = int(user_input)
    print("Le double de votre nombre est:", num * 2)
except ValueError:
    print("La valeur ne peut pas être convertie en entier")
except KeyboardInterrupt:
    print("Interruption clavier détectée")
except:
    print("Gestionnaire d'exception général")
finally:
    print("Ce code sera exécuté dans tous les cas")

Ici, nous avons trois blocs "except". Le premier intercepte les `ValueError`, le deuxième les `KeyboardInterrupt`. Le dernier, sans type d'exception spécifié, intercepte toutes les autres exceptions non traitées par les blocs précédents.

En exécutant ce code, vous devriez obtenir un résultat similaire à celui-ci :

Lorsqu'une exception est levée, vous pouvez accéder à plus d'informations via l'objet exception. Pour cela, vous utilisez le mot-clé "as" :

try:
    user_input = input("Entrez un nombre: ")
    num = int(user_input)
    print("Le double de votre nombre est:", num * 2)
except ValueError as e:
    print("Erreur de valeur:", e)
except KeyboardInterrupt as e:
    print("Interruption clavier:", e)
except Exception as e:
    print("Autre exception:", e)

Comment lever des exceptions

Jusqu'à présent, nous avons vu comment gérer les exceptions levées par d'autres fonctions. Cependant, il est également possible de déclencher des exceptions dans votre propre code. Pour cela, vous utilisez le mot-clé "raise". Vous devez également indiquer la classe d'exception que vous souhaitez lever, ainsi qu'un message descriptif pour l'exception.

Dans l'exemple ci-dessous, nous utilisons la classe "Exception" pour lever une exception générique. Nous passons le message d'erreur au constructeur de la classe :

raise Exception('Une erreur est survenue')

Si vous exécutez ce code, vous obtiendrez un résultat similaire à celui-ci :

Vous pouvez également spécifier des types d'exceptions plus précis. Par exemple, vous pouvez lever une `TypeError` lorsque le type de données d'une valeur est incorrect :

def double(x):
    if isinstance(x, int):
        return x * 2
    else:
        raise TypeError('x doit être un entier')

Ou, si une valeur est en dehors des limites acceptables, vous pouvez lever une `ValueError` :

def say_hello(name):
    if name == '':
        raise ValueError('Valeur hors limites')
    else:
        print('Bonjour', name)

Vous pouvez même créer vos propres types d'exceptions en créant une sous-classe de la classe `Exception` :

class InvalidHTTPMethod(Exception):
    pass

Ici, nous avons défini une classe `InvalidHTTPMethod` qui hérite de `Exception`. On peut l'utiliser de la même manière que les exceptions prédéfinies :

raise InvalidHTTPMethod('La méthode doit être GET ou POST')

Cas d'utilisation courants de la gestion des exceptions

La gestion des exceptions est appliquée dans de nombreux contextes. L'exemple précédent a illustré son utilité pour gérer des erreurs d'entrée utilisateur. Cette section explore deux scénarios supplémentaires où la gestion des exceptions est particulièrement utile : la gestion des erreurs lors de requêtes réseau et la gestion des erreurs lors de la lecture de fichiers.

Requêtes réseau

Dans l'exemple suivant, nous envoyons une requête à Google. Nous mettons en place la gestion des exceptions pour intercepter et traiter les erreurs possibles. Ces exceptions sont définies dans l'objet `requests.exceptions`.

import requests

try:
    response = requests.get("https://google.com")

    if 200 <= response.status_code < 300:
        print("Requête réussie!")
    else:
        print(f"Échec de la requête, code de statut : {response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"Exception de requête : {e}")
except requests.exceptions.ConnectionError as e:
    print(f"Erreur de connexion : {e}")
except requests.exceptions.Timeout as e:
    print(f"Délai d'attente dépassé : {e}")
except requests.exceptions.TooManyRedirects as e:
    print(f"Trop de redirections : {e}")
except requests.exceptions.HTTPError as e:
    print(f"Erreur HTTP : {e}")
except Exception as e:
    print(f"Erreur inattendue : {e}")

Lecture de données depuis un fichier

Dans ce dernier exemple, nous lisons les données du fichier "hello.txt". Nous traitons les exceptions courantes qui peuvent survenir, comme `FileNotFoundError` et `IOError` :

try:
    with open(file_path, 'r') as file:
        data = file.read()
        print("Contenu du fichier:")
        print(data)
except FileNotFoundError as e:
    print(f"Fichier introuvable : {e}")
except IOError as e:
    print(f"Erreur d'entrée/sortie : {e}")
except Exception as e:
    print(f"Erreur inattendue : {e}")

Conclusion

Cet article a exploré la nature des exceptions et les raisons pour lesquelles elles sont levées. Nous avons vu qu'une bonne gestion des exceptions est cruciale pour améliorer la fiabilité des applications et éviter des plantages inattendus. Nous avons également expliqué comment gérer les exceptions à l'aide de la construction "try...except" et comment déclencher des exceptions personnalisées.

Pour aller plus loin, explorez les types d'erreurs Python les plus fréquents et découvrez comment les résoudre.

Auteur
France

Rédacteur tech, guides pratiques et astuces numériques.