Exceptions Python KeyError et comment les gérer

Exceptions Python KeyError et comment les gérer

L'exceptionKeyError de Python est une exception courante rencontrée par les débutants. Savoir pourquoi unKeyError peut être déclenché et des solutions pour l'empêcher d'arrêter votre programme sont des étapes essentielles pour s'améliorer en tant que programmeur Python.

À la fin de ce didacticiel, vous saurez:

  • Ce que signifie généralement un PythonKeyError

  • Où d'autre vous pourriez voir unKeyError dans la bibliothèque standard

  • Comment gérer unKeyError lorsque vous le voyez

Free Bonus:Click here to get our free Python Cheat Sheet qui vous montre les bases de Python 3, comme travailler avec des types de données, des dictionnaires, des listes et des fonctions Python.

Ce que signifie généralement un PythonKeyError

Un PythonKeyErrorexception est ce qui est déclenché lorsque vous essayez d'accéder à une clé qui n'est pas dans undictionary (dict).

Leofficial documentation de Python indique que leKeyError est déclenché lorsqu'une clé de mappage est accédée et n'est pas trouvée dans le mappage. Un mappage est une structure de données qui mappe un ensemble de valeurs à un autre. Le mappage le plus courant en Python est le dictionnaire.

Le PythonKeyError est un type d'exceptionLookupError et indique qu'il y a eu un problème pour récupérer la clé que vous recherchiez. Lorsque vous voyez unKeyError, la signification sémantique est que la clé recherchée n'a pas pu être trouvée.

Dans l'exemple ci-dessous, vous pouvez voir un dictionnaire (ages) défini avec l'âge de trois personnes. Lorsque vous essayez d'accéder à une clé qui n'est pas dans le dictionnaire, unKeyError est déclenché:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'Michael'

Ici, la tentative d'accès à la clé'Michael' dans le dictionnaireages entraîne le déclenchement d'unKeyError. Au bas du traçage, vous obtenez les informations pertinentes:

  • Le fait qu'unKeyError a été soulevé

  • La clé introuvable, à savoir'Michael'

L'avant-dernière ligne vous indique quelle ligne a déclenché l'exception. Ces informations sont plus utiles lorsque vous exécutez du code Python à partir d'un fichier.

Note: Lorsqu'une exception est déclenchée en Python, elle est effectuée avec untraceback. Le retraçage vous donne toutes les informations pertinentes pour pouvoir déterminer pourquoi l'exception a été déclenchée et ce qui l'a provoquée.

Apprendre à lire un traceback Python et comprendre ce qu'il vous dit est crucial pour vous améliorer en tant que programmeur Python.

Dans le programme ci-dessous, vous pouvez voir le dictionnaireages redéfini. Cette fois, vous serez invité à fournir le nom de la personne pour récupérer l'âge de:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 print(f'{person} is {ages[person]} years old.')

Ce code prendra le nom que vous fournissez à l'invite et tentera de récupérer l'âge de cette personne. Tout ce que vous saisissez à l'invite sera utilisé comme clé du dictionnaireages, à la ligne 4.

En répétant l'exemple qui a échoué ci-dessus, nous obtenons un autre traçage, cette fois avec des informations sur la ligne du fichier à partir de laquelle leKeyError est généré:

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in 
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

Le programme échoue lorsque vous donnez une clé qui n'est pas dans le dictionnaire. Ici, les dernières lignes du traçage indiquent le problème. File "ages.py", line 4, in <module> vous indique quelle ligne de quel fichier a déclenché l'exceptionKeyError résultante. Ensuite, on vous montre cette ligne. Enfin, l'exceptionKeyError fournit la clé manquante.

Ainsi, vous pouvez voir que la dernière ligne de traceback deKeyError ne vous donne pas suffisamment d'informations en elle-même, mais les lignes qui la précèdent peuvent vous aider à comprendre ce qui ne va pas.

Note: Comme dans l'exemple ci-dessus, la plupart des autres exemples de ce tutoriel utilisentf-strings, qui ont été introduits dans Python 3.6.

Où sinon vous pourriez voir un PythonKeyError dans la bibliothèque standard

La grande majorité du temps, un PythonKeyError est déclenché car une clé n'est pas trouvée dans un dictionnaire ou une sous-classe de dictionnaire (commeos.environ).

Dans de rares cas, vous pouvez également le voir déclenché à d’autres endroits de la bibliothèque standard de Python, comme dans le modulezipfile, si un élément n’est pas trouvé dans une archive ZIP. Cependant, ces endroits gardent la même signification sémantique que les PythonKeyError, qui ne trouve pas la clé demandée.

Dans l'exemple suivant, vous pouvez voir l'utilisation de la classezipfile.ZipFile pour extraire des informations sur une archive ZIP à l'aide de.getinfo():

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "", line 1, in 
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

Cela ne ressemble pas vraiment à une recherche de clé de dictionnaire. Au lieu de cela, c'est un appel àzipfile.ZipFile.getinfo() qui déclenche l'exception.

Le retraçage a également un aspect un peu différent avec un peu plus d'informations fournies que la clé manquante:KeyError: "There is no item named 'something' in the archive".

La dernière chose à noter ici est que la ligne qui a soulevé lesKeyError n'est pas dans votre code. Il se trouve dans le code dezipfile, mais les lignes précédentes du traçage indiquent quelles lignes de votre code ont causé le problème.

Lorsque vous devez élever un PythonKeyError dans votre propre code

Il peut y avoir des moments où cela a du sens pouryou to raise une exception PythonKeyError dans votre propre code. Cela peut être fait en utilisant le mot-cléraise et en appelant l'exceptionKeyError:

raise KeyError(message)

Habituellement, lesmessage seraient la clé manquante. Cependant, comme dans le cas du packagezipfile, vous pouvez choisir de donner un peu plus d'informations pour aider le prochain développeur à mieux comprendre ce qui ne va pas.

Si vous décidez de lever un PythonKeyError dans votre propre code, assurez-vous simplement que votre cas d'utilisation correspond à la signification sémantique derrière l'exception. Il doit indiquer que la clé recherchée est introuvable.

Comment gérer un PythonKeyError lorsque vous le voyez

Lorsque vous rencontrez unKeyError, il existe quelques méthodes standard pour le gérer. Selon votre cas d'utilisation, certaines de ces solutions peuvent être meilleures que d'autres. Le but ultime est d'empêcher le déclenchement d'exceptions inattendues deKeyError.

La solution habituelle:.get()

SiKeyError est déclenché à partir d'une recherche de clé de dictionnaire ayant échoué dans votre propre code, vous pouvez utiliser.get() pour renvoyer soit la valeur trouvée à la clé spécifiée, soit une valeur par défaut.

Tout comme l'exemple de récupération d'âge d'avant, l'exemple suivant montre une meilleure façon d'obtenir l'âge du dictionnaire à l'aide de la clé fournie à l'invite:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 age = ages.get(person)
 6
 7 if age:
 8     print(f'{person} is {age} years old.')
 9 else:
10     print(f"{person}'s age is unknown.")

Ici, la ligne 5 montre comment vous pouvez obtenir la valeur d'âge deages en utilisant.get(). Cela se traduira par la variableage ayant la valeur d'âge trouvée dans le dictionnaire pour la clé fournie ou une valeur par défaut,None dans ce cas.

Cette fois, vous n'obtiendrez pas une exceptionKeyError levée en raison de l'utilisation de la méthode.get() plus sûre pour obtenir l'âge plutôt que d'essayer d'accéder directement à la clé:

$ python ages.py
Get age for: Michael
Michael's age is unknown.

Dans l'exemple d'exécution ci-dessus, leKeyError n'est plus levé lorsqu'une clé incorrecte est fournie. La clé'Michael' n'est pas trouvée dans le dictionnaire, mais en utilisant.get(), nous obtenons unNone retourné plutôt qu'unKeyError élevé.

La variableage aura soit l'âge de la personne trouvé dans le dictionnaire, soit la valeur par défaut (None par défaut). Vous pouvez également spécifier une valeur par défaut différente dans l'appel de.get() en passant un deuxième argument.

Il s'agit de la ligne 5 de l'exemple ci-dessus avec un âge par défaut différent spécifié à l'aide de.get():

age = ages.get(person, 0)

Ici, au lieu de'Michael' renvoyantNone, il renverrait0 car la clé n’est pas trouvée, et la valeur par défaut à renvoyer est maintenant0.

La solution rare: vérification des clés

Il y a des moments où vous devez déterminer l'existence d'une clé dans un dictionnaire. Dans ces cas, l'utilisation de.get() peut ne pas vous donner les informations correctes. Obtenir unNone renvoyé par un appel à.get() peut signifier que la clé n’a pas été trouvée ou que la valeur trouvée à la clé dans le dictionnaire est en faitNone.

Avec un dictionnaire ou un objet de type dictionnaire, vous pouvez utiliser l'opérateurin pour déterminer si une clé se trouve dans le mappage. Cet opérateur renverra une valeur booléenne (True ouFalse) indiquant si la clé se trouve dans le dictionnaire.

Dans cet exemple, vous obtenez un dictionnaireresponse en appelant une API. Cette réponse peut avoir une valeur de cléerror définie dans la réponse, ce qui indiquerait que la réponse est dans un état d'erreur:

 1 # parse_api_response.py
 2 ...
 3 # Assuming you got a `response` from calling an API that might
 4 # have an error key in the `response` if something went wrong
 5
 6 if 'error' in response:
 7     ...  # Parse the error state
 8 else:
 9     ...  # Parse the success state

Ici, il y a une différence pour vérifier si la cléerror existe dans leresponse et obtenir une valeur par défaut de la clé. Il s'agit d'un cas rare où ce que vous recherchez réellement est si la clé est dans le dictionnaire et non quelle est la valeur de cette clé.

La solution générale:tryexcept

Comme pour toute exception, vous pouvez toujours utiliser le bloctryexcept pour isoler le code potentiel de levée d'exceptions et fournir une solution de sauvegarde.

Vous pouvez utiliser le bloctryexcept dans un exemple similaire au précédent, mais cette fois en fournissant un message par défaut à imprimer si unKeyError est déclenché dans le cas normal:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5
 6 try:
 7     print(f'{person} is {ages[person]} years old.')
 8 except KeyError:
 9     print(f"{person}'s age is unknown.")

Ici, vous pouvez voir le cas normal dans le bloctry d'impression du nom et de l'âge de la personne. Le cas de sauvegarde est dans le blocexcept, où si unKeyError est déclenché dans le cas normal, alors le cas de sauvegarde consiste à imprimer un message différent.

La solution de bloctryexcept est également une excellente solution pour d'autres emplacements qui pourraient ne pas prendre en charge.get() ou l'opérateurin. C'est également la meilleure solution si leKeyError est généré à partir du code d'une autre personne.

Voici un exemple utilisant à nouveau le packagezipfile. Cette fois, le bloctryexcept nous donne un moyen d'empêcher l'exceptionKeyError d'arrêter le programme:

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

Puisque la classeZipFile ne fournit pas.get(), comme le fait le dictionnaire, vous devez utiliser la solutiontryexcept. Dans cet exemple, vous n’avez pas besoin de savoir à l’avance quelles valeurs sont valides à transmettre à.getinfo().

Conclusion

Vous connaissez maintenant certains endroits courants où l'exceptionKeyError de Python pourrait être déclenchée et quelques solutions intéressantes que vous pourriez utiliser pour les empêcher d'arrêter votre programme.

Maintenant, la prochaine fois que vous verrez unKeyError déclenché, vous saurez que c'est probablement juste une mauvaise recherche de clé de dictionnaire. Vous pourrez également trouver toutes les informations dont vous avez besoin pour déterminer d'où vient l'erreur en consultant les dernières lignes du traçage.

Si le problème est une recherche de clé de dictionnaire dans votre propre code, vous pouvez passer de l'accès à la clé directement sur le dictionnaire à l'utilisation de la méthode.get() plus sûre avec une valeur de retour par défaut. Si le problème ne vient pas de votre propre code, utiliser le bloctryexcept est votre meilleur moyen de contrôler le flux de votre code.

Les exceptions n'ont pas à être effrayantes. Une fois que vous savez comment comprendre les informations qui vous sont fournies dans leurs retraits et la cause première de l'exception, vous pouvez utiliser ces solutions pour rendre vos programmes plus fluides de manière prévisible.