
En Python, try et except sont utilisés pour gérer les exceptions (= erreurs détectées lors de l’exécution). Avec try et except, même si une exception se produit, le processus continue sans se terminer. Vous pouvez utiliser else et finally pour définir le processus de fin.
Cet article décrit le contenu suivant.
- Gestion des exceptions de base en Python :
try ... except ...
- Capturer plusieurs exceptions
- Appliquer différentes opérations à plusieurs exceptions
- Appliquer la même opération à plusieurs exceptions
- Attrapez toutes les exceptions
- Caractère générique sauf (Nu sauf)
- Classe de base :
Exception
- Exécuter l’action s’il n’y a pas d’exception :
try ... except ... else ...
- Action de nettoyage :
try ... except ... finally ...
- Ignorer les exceptions :
pass
- Exemple pratique : Lecture de fichiers image
Gestion des exceptions de base en Python :try ... except ...
Par exemple, lorsqu’une division par zéro est tentée, ZeroDivisionError est déclenchée et le processus se termine.
# print(1 / 0)
# ZeroDivisionError: division by zero
Pour intercepter cette exception, écrivez comme suit :
try:
print(1 / 0)
except ZeroDivisionError:
print('Error')
# Error
En définissant except as :, l’objet exception est stocké dans la variable. Vous pouvez spécifier n’importe quel nom pour la variable, mais des noms tels que e et err sont souvent utilisés.
L’objet d’exception contient des messages d’erreur qui sont générés lorsqu’une exception se produit, et vous pouvez vérifier les détails de l’erreur en les publiant.
try:
print(1 / 0)
except ZeroDivisionError as e:
print(e)
print(type(e))
# division by zero
# <class 'ZeroDivisionError'>
En Python2, vous devez écrire comme sauf , :.
Vous pouvez également spécifier une classe de base. Par exemple, ArithmeticError est la classe de base de ZeroDivisionError. La variable stocke l’objet exception de la classe dérivée qui s’est réellement produite.
print(issubclass(ZeroDivisionError, ArithmeticError))
# True
try:
print(1 / 0)
except ArithmeticError as e:
print(e)
print(type(e))
# division by zero
# <class 'ZeroDivisionError'>
Consultez la documentation officielle pour les exceptions intégrées dans Python.
Lorsqu’une exception se produit dans la clause try, le processus suivant dans la clause try est ignoré.
Comme illustré dans l’exemple ci-dessous, si une exception se produit au milieu de la boucle for, la boucle for se termine à ce point et le processus de la clause except est exécuté.
try:
for i in [-2, -1, 0, 1, 2]:
print(1 / i)
except ZeroDivisionError as e:
print(e)
# -0.5
# -1.0
# division by zero
Vous pouvez spécifier le processus à exécuter après la clause except dans les clauses else et finally décrites plus loin.
Capturer plusieurs exceptions
Définissez la fonction suivante qui intercepte ZeroDivisionError.
def divide(a, b):
try:
print(a / b)
except ZeroDivisionError as e:
print('catch ZeroDivisionError:', e)
Avec cette fonction, ZeroDivisionError peut être intercepté, mais les autres exceptions ne peuvent pas être interceptées.
divide(1, 0)
# catch ZeroDivisionError: division by zero
# divide('a', 'b')
# TypeError: unsupported operand type(s) for /: 'str' and 'str'
Appliquer différentes opérations à plusieurs exceptions
Vous pouvez spécifier plusieurs clauses except et définir différentes opérations pour chaque exception.
def divide_each(a, b):
try:
print(a / b)
except ZeroDivisionError as e:
print('catch ZeroDivisionError:', e)
except TypeError as e:
print('catch TypeError:', e)
divide_each(1, 0)
# catch ZeroDivisionError: division by zero
divide_each('a', 'b')
# catch TypeError: unsupported operand type(s) for /: 'str' and 'str'
Appliquer la même opération à plusieurs exceptions
Vous pouvez spécifier plusieurs noms d’exception en tant que tuple dans une clause except.
def divide_same(a, b):
try:
print(a / b)
except (ZeroDivisionError, TypeError) as e:
print(e)
divide_same(1, 0)
# division by zero
divide_same('a', 'b')
# unsupported operand type(s) for /: 'str' and 'str'
Attrapez toutes les exceptions
Il est également possible d’attraper toutes les exceptions sans spécifier d’exceptions.
Caractère générique sauf (Nu sauf)
Toutes les exceptions peuvent être interceptées en omettant le nom de l’exception dans la clause except. S’il existe plusieurs clauses except, le nom de l’exception ne peut être omis que dans la dernière clause except.
La clause except sans noms d’exception est appelée wildcard except, bare except, etc. Veillez à l’utiliser comme décrit dans la documentation officielle.
La dernière clause except peut omettre le ou les noms d’exception, pour servir de caractère générique. Utilisez-le avec une extrême prudence, car il est facile de masquer ainsi une véritable erreur de programmation !
8. Erreurs et exceptions – Gestion des exceptions — Documentation Python 3.9.0
def divide_wildcard(a, b):
try:
print(a / b)
except:
print('Error')
divide_wildcard(1, 0)
# Error
divide_wildcard('a', 'b')
# Error
À l’exception des caractères génériques, toutes les exceptions, y compris SystemExit (déclenchée par sys.exit(), etc.) et KeyboardInterrupt (déclenchée en saisissant la touche d’interruption Ctrl + C) sont interceptées. Dans de nombreux cas, il est préférable de terminer le processus sans intercepter ces exceptions, il est donc préférable d’utiliser Exception décrit ci-après.
Classe de base :Exception
Vous pouvez spécifier Exception dans la clause except, qui est la classe de base pour toutes les exceptions intégrées ne sortant pas du système.
def divide_exception(a, b):
try:
print(a / b)
except Exception as e:
print(e)
divide_exception(1, 0)
# division by zero
divide_exception('a', 'b')
# unsupported operand type(s) for /: 'str' and 'str'
La hiérarchie des classes pour les exceptions intégrées est la suivante.
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ...
...
Étant donné que SystemExit et KeyboardInterrupt n’héritent pas d’Exception, si Exception est spécifié dans la clause except, sys.exit() et l’exception de l’entrée de la touche d’interruption ne seront pas interceptées.
Cette exception est levée par la fonction sys.exit(). Il hérite de BaseException au lieu d’Exception afin qu’il ne soit pas accidentellement intercepté par le code qui intercepte Exception. Cela permet à l’exception de se propager correctement et de provoquer la fermeture de l’interpréteur.
Exceptions intégrées – SystemExit — documentation Python 3.9.0
Levé lorsque l’utilisateur appuie sur la touche d’interruption (normalement Control-C ou Delete). Pendant l’exécution, une vérification des interruptions est effectuée régulièrement. L’exception hérite de BaseException afin de ne pas être accidentellement interceptée par le code qui intercepte Exception et ainsi empêcher l’interpréteur de sortir.
Exceptions intégrées – KeyboardInterrupt — documentation Python 3.9.0
La classe de base pour toutes les exceptions intégrées, y compris SystemExit et KeyboardInterrupt, isBaseException. Si vous spécifiez BaseException au lieu de Exception dans la clause except, toutes les exceptions seront interceptées ainsi que le caractère générique sauf.
Il est préférable de spécifier autant que possible les exceptions attendues dans la clause except car la capture même d’une exception inattendue peut provoquer un bogue.
Exécuter l’action s’il n’y a pas d’exception :try ... except ... else ...
Vous pouvez spécifier l’action à exécuter s’il n’y a pas d’exception dans la clause else. Si une exception se produit et est interceptée par except, l’action dans la clause else n’est pas exécutée.
def divide_else(a, b):
try:
print(a / b)
except ZeroDivisionError as e:
print('catch ZeroDivisionError:', e)
else:
print('finish (no error)')
divide_else(1, 2)
# 0.5
# finish (no error)
divide_else(1, 0)
# catch ZeroDivisionError: division by zero
Action de nettoyage :try ... except ... finally ...
Dans la clause finally, vous pouvez spécifier l’action de nettoyage à exécuter, qu’une exception se produise ou non.
def divide_finally(a, b):
try:
print(a / b)
except ZeroDivisionError as e:
print('catch ZeroDivisionError:', e)
finally:
print('all finish')
divide_finally(1, 2)
# 0.5
# all finish
divide_finally(1, 0)
# catch ZeroDivisionError: division by zero
# all finish
Vous pouvez également utiliser les clauses else et finally ensemble. Si aucune exception ne se produit, la clause else est exécutée, puis la clause finally est exécutée.
def divide_else_finally(a, b):
try:
print(a / b)
except ZeroDivisionError as e:
print('catch ZeroDivisionError:', e)
else:
print('finish (no error)')
finally:
print('all finish')
divide_else_finally(1, 2)
# 0.5
# finish (no error)
# all finish
divide_else_finally(1, 0)
# catch ZeroDivisionError: division by zero
# all finish
Ignorer les exceptions :pass
Si vous souhaitez intercepter une exception et la transmettre sans rien faire, utilisez pass.
def divide_pass(a, b):
try:
print(a / b)
except ZeroDivisionError:
pass
divide_pass(1, 0)
Consultez l’article suivant pour plus de détails sur l’instruction pass.
Exemple pratique : Lecture de fichiers image
Un exemple pratique d’utilisation de la gestion des exceptions est la lecture de fichiers image.
Voici un exemple de redimensionnement des fichiers image dans le dossier à l’aide de Pillow.
Sans gestion des exceptions :
Obtenez tous les chemins de fichiers dans le dossier avec glob() et redimensionnez uniquement les fichiers qui correspondent à des extensions spécifiques.
import os
import glob
from PIL import Image
dst_dir = 'data/temp/images_half'
os.makedirs(dst_dir, exist_ok=True)
files = glob.glob('./data/temp/images/*')
for f in files:
root, ext = os.path.splitext(f)
if ext in ['.jpg', '.png']:
img = Image.open(f)
img_resize = img.resize((img.width // 2, img.height // 2))
basename = os.path.basename(root)
img_resize.save(os.path.join(dst_dir, basename + '_half' + ext))
Étant donné que les fichiers image ont diverses extensions, il est difficile de toutes les spécifier.
Avec gestion des exceptions :
files = glob.glob('./data/temp/images/*')
for f in files:
try:
img = Image.open(f)
img_resize = img.resize((img.width // 2, img.height // 2))
root, ext = os.path.splitext(f)
basename = os.path.basename(root)
img_resize.save(os.path.join(dst_dir, basename + '_half' + ext))
except OSError as e:
pass
Tous les fichiers pouvant être ouverts avec Image.open() de Pillow sont redimensionnés.
Le style qui juge explicitement la condition comme le premier s’appelle « LBYL: Look Before You Leap », et le style qui utilise la gestion des exceptions comme le second s’appelle « EAFP: Plus facile de demander pardon que permission ».
Les deux ont des avantages et des inconvénients, mais le processus qui nécessite de nombreuses conditions peut être écrit de manière concise en utilisant la gestion des exceptions.