Python Try...Except
Apprenez les blocs try, except, else et finally en Python avec des exemples clairs. Gérez ZeroDivisionError, ValueError, FileNotFoundError et plus encore.
Lorsque Python rencontre une erreur à l'exécution, il lève une exception — un objet qui représente ce qui s'est mal passé. Sans aucune gestion, une exception termine immédiatement votre programme. L'instruction try...except vous permet d'attraper ces exceptions, d'y répondre de manière appropriée et de maintenir votre programme en cours d'exécution.
Ce chapitre couvre :
- Le bloc
try/except— attraper une exception spécifique - Capturer les détails d'une exception avec
as - Les clauses
exceptmultiples et la capture de plusieurs exceptions à la fois - Le bloc
else— code qui s'exécute uniquement lorsqu'aucune exception ne se produit - Le bloc
finally— code de nettoyage qui s'exécute toujours - Les exceptions intégrées courantes et quand elles se produisent
- La re-levée d'exceptions
- Les bonnes pratiques et les erreurs courantes
Le bloc try...except de base
Entourez le code susceptible d'échouer dans un bloc try. Si Python lève une exception, l'exécution saute vers le bloc except correspondant au lieu de planter.
Sortie :
Error: division by zeroPython tente la division, lève ZeroDivisionError, et le bloc except la gère. La clause as e lie l'objet exception à e afin que vous puissiez inspecter ou journaliser le message.
Si le bloc try réussit, le bloc except est entièrement ignoré.
Attraper un type d'exception spécifique
Nommez toujours le type d'exception que vous attendez. Attraper un type nommé rend votre intention claire et évite de masquer accidentellement des bugs sans rapport.
try:
number = int("abc")
except ValueError as e:
print(f"Could not convert: {e}")Sortie :
Could not convert: invalid literal for int() with base 10: 'abc'int("abc") lève ValueError car "abc" n'est pas un entier valide. Spécifier ValueError dans la clause except signifie que toute autre exception inattendue se propagera quand même et apparaîtra comme une erreur plutôt que d'être silencieusement ignorée.
Les clauses except multiples
Un seul bloc try peut avoir plusieurs clauses except — Python les vérifie de haut en bas et exécute la première correspondance.
def safe_index(items, index):
try:
return items[index]
except IndexError:
print("Index out of range.")
except TypeError:
print("Index must be an integer.")
safe_index([1, 2, 3], 10) # IndexError
safe_index([1, 2, 3], "a") # TypeErrorSortie :
Index out of range.
Index must be an integer.L'ordre est important : placez les types d'exceptions plus spécifiques avant les types plus larges afin que le gestionnaire spécifique s'exécute en premier.
Attraper plusieurs exceptions dans une seule clause
Lorsque deux exceptions ou plus méritent la même réponse, regroupez-les dans un tuple :
try:
value = int("not-a-number")
except (ValueError, TypeError) as e:
print(f"Input error: {e}")Sortie :
Input error: invalid literal for int() with base 10: 'not-a-number'Le bloc else
Le bloc else s'exécute uniquement lorsque le bloc try se termine sans lever aucune exception. Utilisez-le pour le code qui doit s'exécuter en cas de succès mais qui n'a pas lui-même besoin de protection contre les erreurs :
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print(f"Division succeeded. Result: {result}")Sortie :
Division succeeded. Result: 5.0Garder la logique du chemin de succès dans else (plutôt qu'au bas du bloc try) évite d'attraper accidentellement des exceptions que le code du chemin de succès lui-même pourrait lever.
Le bloc finally
Le bloc finally s'exécute quoi qu'il arrive — que le bloc try réussisse, qu'une exception soit attrapée, ou qu'une exception se propage sans être attrapée. Utilisez-le pour le nettoyage : fermer des fichiers, libérer des verrous ou se déconnecter d'une base de données.
try:
result = 10 / 0
except ZeroDivisionError:
print("Error caught.")
finally:
print("This always runs — cleanup goes here.")Sortie :
Error caught.
This always runs — cleanup goes here.Même si vous commentez le bloc except, finally s'exécute quand même avant que Python ne propage l'exception.
Structure complète en un coup d'œil
try:
# code that may raise an exception
except SomeException as e:
# handle the exception
except (AnotherError, YetAnother):
# handle either of these
else:
# runs only when try succeeded
finally:
# always runsLes exceptions intégrées courantes
| Exception | Quand elle se produit |
|---|---|
ZeroDivisionError | Division ou modulo par zéro |
ValueError | Bon type, mauvaise valeur (ex. int("abc")) |
TypeError | Opération appliquée au mauvais type |
IndexError | Indice de séquence hors limites |
KeyError | Clé de dictionnaire introuvable |
FileNotFoundError | Fichier ou répertoire inexistant |
AttributeError | L'objet n'a pas cet attribut |
ImportError | Le module ne peut pas être importé |
NameError | Le nom de variable n'est pas défini |
Toutes ces exceptions héritent de la classe de base Exception. Vous pouvez attraper Exception pour les gérer toutes dans une seule clause, mais préférez les types spécifiques dans la mesure du possible.
Gérer un fichier manquant
try:
with open("data.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("Error: File not found.")Sortie (lorsque data.txt n'existe pas) :
Error: File not found.Re-lever une exception
Parfois, vous souhaitez journaliser une exception ou effectuer un nettoyage partiel, mais laisser quand même l'exception se propager à l'appelant. Utilisez un raise nu à l'intérieur d'un bloc except :
def process():
try:
result = 10 / 0
except ZeroDivisionError:
print("Logging error...")
raise # re-raises the original ZeroDivisionError
try:
process()
except ZeroDivisionError as e:
print(f"Outer handler caught: {e}")Sortie :
Logging error...
Outer handler caught: division by zeroLe raise nu préserve la traceback originale afin que le débogage ne soit pas plus difficile qu'en l'absence du gestionnaire.
Attraper la classe de base Exception
Vous pouvez utiliser Exception comme gestionnaire fourre-tout pour toute erreur qui ne fait pas quitter le système :
try:
result = 10 / 0
except Exception as e:
print(f"An error occurred: {type(e).__name__}: {e}")Sortie :
An error occurred: ZeroDivisionError: division by zerotype(e).__name__ vous donne le nom de la classe spécifique même lorsque vous attrapez via la classe de base. Cela est utile dans les gestionnaires de niveau supérieur où vous souhaitez journaliser chaque erreur inattendue.
bare except — et pourquoi l'éviter
Un bare except (sans type d'exception) attrape littéralement tout, y compris KeyboardInterrupt (Ctrl+C) et SystemExit, rendant votre programme difficile à interrompre :
# Avoid this pattern
try:
result = 10 / 0
except:
print("Some error occurred")Préférez except Exception si vous avez besoin d'un large filet, car cela laisse quand même KeyboardInterrupt et SystemExit se propager normalement.
Bonnes pratiques
- Soyez spécifique. Attrapez le type d'exception le plus étroit qui ait du sens.
- Ne silenciez pas les exceptions. Journalisez au minimum l'erreur ; ne laissez jamais un bloc
exceptvide. - Utilisez
elsepour le code du chemin de succès. Cela maintient le bloctryaussi petit que possible. - Utilisez
finallypour le nettoyage. Ou, encore mieux, utilisez une instructionwith— voir Python with Statement. - Évitez le
bare except. Utilisezexcept Exceptionsi vous avez besoin d'un large filet. - Re-levez si nécessaire. Si vous ne pouvez pas gérer complètement l'erreur, laissez-la se propager avec
raise.
Pour lever des exceptions délibérément et créer vos propres classes d'exceptions, voir Python raise and Custom Exceptions.