En Python, toutes les exceptions dérivent de la classe BaseException. Cela signifie que chaque exception en Python est une instance de BaseException ou de l’une de ses sous-classes.
La classe BaseException est la classe la plus haute dans la hiérarchie des exceptions. Elle fournit quelques méthodes communes que toutes les exceptions peuvent utiliser, comme __str__ et __repr__. Cependant, il est déconseillé d’utiliser directement BaseException dans votre code, car elle est trop générale et risque d’intercepter tout type d’exception. À la place, vous devriez recourir à des classes d’exception plus spécifiques qui sont des sous-classes de BaseException. Python offre plusieurs classes d’exception intégrées que vous pouvez employer, et vous pouvez également créer vos propres classes d’exception personnalisées :
The hierarchy of built-in exception classes in Python (from the official Python docs).
Cela signifie que FileNotFoundError est une sous-classe de OSError, elle-même sous-classe de la classe Exception, qui hérite finalement de BaseException.
Respecter la hiérarchie des exceptions
Lorsque vous utilisez plusieurs instructions except, il est important de respecter la hiérarchie des exceptions en Python. Autrement dit, si vous interceptez une classe d’exception de base telle que Exception, vous devriez d’abord intercepter des exceptions plus spécifiques. Si vous placez une instruction except d’une classe plus spécifique après la classe de base, ce bloc ne sera jamais exécuté :
try:
# some code that may raise an exception
except ValueError:
# handle the ValueError
except Exception:
# handle any other exception
Dans cet exemple, l’exception ValueError est interceptée en premier. Si le code génère n’importe quelle autre exception dérivée de Exception, le bloc du second except sera exécuté. Cependant, il n’est pas recommandé d’intercepter directement Exception, car c’est trop large et cela peut couvrir tout type d’exception. Il est préférable d’intercepter des exceptions plus spécifiques autant que possible :
Si le code dans le bloc try soulève un TypeError ou un ValueError, le bloc except correspondant sera exécuté. Si le code déclenche une autre exception dérivée de Exception, le bloc dans le troisième except s’exécutera.
Si nous plaçons l’exception de base en premier dans le bloc except, cela empêchera l’exécution des autres :
try:
# some code that may raise an exception
except Exception as e: # This will catch all the errors
print(f'An error occurred: {e}')
except ValueError: # This will never be executed
print('A ValueError occurred')
except TypeError: # This will never be executed
print('A TypeError occurred')
Dans cet exemple, le bloc try peut soulever n’importe quelle exception. Toutefois, la première instruction except intercepte déjà la classe de base Exception, donc elle captera toute exception soulevée. Le message d’erreur sera imprimé, et les autres instructions except ne s’exécuteront pas.
Défi: Analyser le fichier
Vous travaillez comme ingénieur logiciel dans une startup qui manipule de grandes quantités de données. Récemment, l’équipe a décidé d’utiliser des fichiers JSON pour stocker et traiter ces données. Ces données sont essentielles au fonctionnement de la startup, et votre rôle est d’écrire un programme Python qui lise et analyse ces fichiers JSON.
Cependant, à cause de la grande quantité de données et du fait que plusieurs personnes y travaillent, certaines erreurs surviennent fréquemment :
Il arrive parfois que le fichier de données n’existe pas.
Il arrive parfois que le fichier de données soit vide.
Il arrive parfois que le fichier de données contienne du contenu qui n’est pas un JSON valide.
Votre programme doit s’assurer de gérer ces exceptions sans planter et fournir des messages d’erreur clairs pour que l’équipe de données puisse identifier et résoudre le problème rapidement.
Le programme doit prendre en entrée une chaîne de caractères représentant le nom du fichier et gérer les cas suivants :
Si le fichier n’existe pas, il doit lever une FileNotFoundError et afficher un message d’erreur approprié.
Si le fichier est vide, il doit lever une ValueError et afficher un message d’erreur approprié.
Si le contenu du fichier n’est pas un JSON valide, il doit lever une json.JSONDecodeError (qui est une sous-classe de ValueError) et afficher un message d’erreur approprié. Lors du relèvement de cette exception, vous devrez fournir les attributs doc et pos en paramètres.
💡
except json.JSONDecodeError as e:
Chacune de ces exceptions doit être gérée indépendamment, et votre programme doit délivrer un message d’erreur précis pour chaque situation.
Entrée
Sortie
nonexistent_file.json
FileNotFoundError: File 'nonexistent_file.json' does not exist.
empty_file.json
ValueError: File 'empty_file.json' is empty.
invalid_json.json
JSONDecodeError: Content of file 'invalid_json.json' is not valid JSON.: line 1 column 1 (char 0)
success.json
File 'success.json' has been successfully parsed as valid JSON.