Erreurs et exceptions Python3
En tant que débutant en Python, lorsque vous apprendrez pour la première fois la programmation Python, vous verrez souvent des messages d'erreur. Nous ne les avons pas mentionnés auparavant, mais nous les présenterons spécifiquement dans ce chapitre.
Il existe deux types d'erreurs en Python qui sont faciles à identifier : les erreurs de syntaxe et les exceptions.
Erreurs de syntaxe
Les erreurs de syntaxe Python, ou erreurs d'analyse, sont souvent rencontrées par les débutants, comme le montre l'exemple suivant
>>> while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax
Dans cet exemple, la fonction print() Une erreur a été détectée car il manquait deux points (:) devant elle.
L'analyseur signale la ligne en erreur et marque la première erreur trouvée avec une petite flèche.
Exception
Même si la syntaxe du programme Python est correcte, des erreurs peuvent survenir lors de son exécution. Les erreurs détectées lors de l'exécution sont appelées exceptions.
La plupart des exceptions ne seront pas gérées par le programme et sont affichées sous forme de messages d'erreur ici :
>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: division by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Can't convert 'int' object to str implicitly
Les exceptions apparaissent dans différents types, et ces types sont imprimés dans le cadre du message : Les types. dans l'exemple sont ZeroDivisionError, NameError et TypeError.
La partie avant du message d'erreur montre le contexte dans lequel l'exception s'est produite et affiche des informations spécifiques sous la forme d'une pile d'appels.
Gestion des exceptions
Dans l'exemple suivant, l'utilisateur est autorisé à saisir un entier légal, mais l'utilisateur est autorisé à interrompre le programme (en utilisant Control-C ou la méthode fournie par le système d'exploitation système). Les messages interrompus par l’utilisateur génèrent une exception KeyboardInterrupt.
>>> while True: try: x = int(input("Please enter a number: ")) break except ValueError: print("Oops! That was no valid number. Try again ")
L'instruction try fonctionne comme suit
Tout d'abord, la clause try (l'instruction entre le mot-clé try et le mot-clé except) est exécutée
Si aucune exception ne se produit, ignorez la clause except et terminez après l'exécution de la clause try.
Si une exception se produit lors de l'exécution de la clause try, le reste de la clause try sera ignoré. Si le type d'exception correspond au nom après except, la clause except correspondante sera exécutée. Enfin, exécutez le code après l'instruction try.
Si une exception ne correspond à aucune exception, alors l'exception sera transmise à l'essai supérieur.
Une instruction try peut contenir plusieurs clauses except pour gérer différentes exceptions spécifiques. Au plus une branche sera exécutée.
Le gestionnaire ne gérera que les exceptions dans la clause try correspondante, pas les exceptions dans les autres gestionnaires try.
Une clause except peut gérer plusieurs exceptions en même temps. Ces exceptions seront placées entre parenthèses pour former un tuple, par exemple :
except (RuntimeError, TypeError, NameError): pass
La dernière clause except peut ignorer le nom du. exception, il sera utilisé comme caractère générique. Vous pouvez utiliser cette méthode pour imprimer un message d'erreur, puis relancer l'exception.
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except OSError as err: print("OS error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") except: print("Unexpected error:", sys.exc_info()[0]) raise
try L'instruction except a également une clause else facultative. Si cette clause est utilisée, elle doit être placée après toutes les clauses except. Cette clause sera exécutée si aucune exception ne se produit dans la clause try. Par exemple :
for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print('cannot open', arg) else: print(arg, 'has', len(f.readlines()), 'lines') f.close()
Il est préférable d'utiliser la clause else que de mettre toutes les instructions dans la clause try, afin d'éviter certaines exceptions inattendues qui ne sont pas interceptées par except.
La gestion des exceptions gère non seulement les exceptions qui se produisent directement dans la clause try, mais gère également les exceptions lancées dans les fonctions appelées dans la clause (même les fonctions appelées indirectement). Par exemple :
>>> def this_fails(): x = 1/0 >>> try: this_fails() except ZeroDivisionError as err: print('Handling run-time error:', err) Handling run-time error: int division or modulo by zero
Lance une exception
Python utilise l'instruction raise pour lever une exception spécifiée. Par exemple :
>>> raise NameError('HiThere') Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: HiThere
raise Le seul paramètre spécifie l'exception à lever. Il doit s'agir d'une instance d'exception ou d'une classe d'exception (c'est-à-dire une sous-classe d'Exception).
Si vous voulez simplement savoir si cela a généré une exception et que vous ne voulez pas la gérer, une simple instruction raise peut la déclencher à nouveau.
>>> try: raise NameError('HiThere') except NameError: print('An exception flew by!') raise An exception flew by! Traceback (most recent call last): File "<stdin>", line 2, in ? NameError: HiThere
Exceptions définies par l'utilisateur
Vous pouvez avoir vos propres exceptions en créant une nouvelle classe d'exceptions. Les exceptions doivent hériter de la classe Exception, directement ou indirectement, par exemple :
>>> class MyError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) >>> try: raise MyError(2*2) except MyError as e: print('My exception occurred, value:', e.value) My exception occurred, value: 4 >>> raise MyError('oops!') Traceback (most recent call last): File "<stdin>", line 1, in ? __main__.MyError: 'oops!'
Dans cet exemple, la valeur par défaut __init__() de la classe Exception est remplacée.
Les classes <pException peuvent faire tout comme les autres classes, mais elles sont généralement plus simples, ne fournissant que certaines propriétés liées aux erreurs et permettant au code qui gère l'exception d'obtenir facilement ces informations. < p="">Lors de la création d'un module pouvant générer de nombreuses exceptions différentes, une approche courante consiste à créer une classe d'exception de base pour le package, puis à fournir différentes erreurs basées sur cette classe de base. Créez différentes sous-classes. :
class Error(Exception): """Base class for exceptions in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message class TransitionError(Error): """Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message
La plupart des noms d'exceptions se terminent par "Erreur", tout comme les noms d'exceptions standard.
Définir le comportement de nettoyage
L'instruction try a une autre clause facultative qui définit le comportement de nettoyage qui sera exécuté quelles que soient les circonstances. Par exemple :
>>> try: raise KeyboardInterrupt finally: print('Goodbye, world!') Goodbye, world! KeyboardInterrupt
Dans l'exemple ci-dessus, la clause final sera exécutée qu'une exception se produise ou non dans la clause try.
Si une exception est levée dans la clause try (ou dans les clauses except et else) et qu'il n'y a pas d'exception pour l'attraper, alors l'exception sera à nouveau levée après l'exécution de la clausefinal.
Voici un exemple plus complexe (contenant des clauses except et enfin dans la même instruction try) :
>>> def divide(x, y): try: result = x / y except ZeroDivisionError: print("division by zero!") else: print("result is", result) finally: print("executing finally clause") >>> divide(2, 1) result is 2.0 executing finally clause >>> divide(2, 0) division by zero! executing finally clause >>> divide("2", "1") executing finally clause Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'
Comportement de nettoyage prédéfini
Certains L'objet définit un nettoyage standard Que le système l'utilise avec succès ou non, une fois qu'il n'est plus nécessaire, ce comportement de nettoyage standard sera exécuté.
Voici un exemple de tentative d'ouverture d'un fichier puis d'impression du contenu à l'écran :
for line in open("myfile.txt"): print(line, end="")
Le problème avec le code ci-dessus est qu'après l'exécution, le fichier restera ouvert, et n'a pas été fermé.
Le mot-clé with instruction peut garantir que des objets tels que des fichiers exécuteront correctement leurs méthodes de nettoyage après utilisation :
with open("myfile.txt") as f: for line in f: print(line, end="")
Une fois le code ci-dessus exécuté, même si quelque chose s'est mal passé pendant le traitement et le fichier f était toujours fermé.