Inspecter les objets Python
Retour à la liste des articles
05 avril 2019
Un des premiers réflexes lorsqu'un programme a un comportement inattendu doit être d'examiner les objets qui le composent, afin de comprendre l'erreur et pouvoir remonter à sa source.
Cet article explique comment utiliser les fonctions natives dir
et vars
de
Python pour examiner les objets d'un programme.
Prérequis pour cet article
Assure-toi d'avoir les connaissances nécessaires pour cet article en terminant la lecture du chapitre 6 « Un programme dynamique avec Python ».
Tu ne possèdes pas encore Génies du code ? Il s'agit d'une méthode illustrée, adaptée à tous les niveaux, qui te fera découvrir la programmation à travers la réalisation de ton propre site web de A à Z. Les deux premiers chapitres sont disponibles gratuitement dans leur intégralité !
Découvrir Génies du codeAffichage des valeurs pendant l'exécution
Dans les cas simples, l'affichage de certaines valeurs juste avant l'erreur peut donner une indication sur son origine. Prenons comme exemple le programme présenté dans le chapitre 6, au point de contrôle numéro 7 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Comme on l'a vu, le programme plante lorsque tu entres une réponse qui ne fait pas partie des options à choix :
$ python3 quiz_2.py
Quelle est la vitesse de pointe d’un thon?
- 20 km/h
- 40 km/h
- 80 km/h
Votre réponse: 60 km/h
Traceback (most recent call last):
File "/home/julie/Bureau/web/quiz_2.py", line 21, in <module>
correct = show_question(question[0], question[1])
File "/home/julie/Bureau/web/quiz_2.py", line 7, in show_question
if options[answer]:
KeyError: '60 km/h'
Pour comprendre l'origine de cette erreur, on aimerait savoir ce que contient la
variable options
. Pour ce faire, on peut utiliser la fonction print
, qui
affiche le paramètre qui lui est passé.
Commence par télécharger le code du point de
contrôle, enregistre-le (par exemple
sur ton bureau), puis extrais l'archive. Ouvre le fichier quiz_2.py
dans ton
éditeur et ajoute l'instruction print(options)
au-dessus de la ligne if
options[answer]:
pour que le code ressemble à ça :
print(options)
if options[answer]:
# ...
Ouvre maintenant un terminal, rends-toi dans le dossier où se situe le fichier
quiz_2.py
(avec la commande cd
, dont l'utilisation est expliquée en détail
au chapitre 4) puis exécute-le avec la commande python3 quiz_2.py
. Tu
devrais voir les options s'afficher avant l'erreur :
$ python3 quiz_2.py
...
{'20 km/h': False, '40 km/h': False, '80 km/h': True}
...
De cette façon, tu peux voir que l'option 60 km/h
n'est pas présente dans le
dictionnaire d'options, et que l'instruction pointée par l'erreur essaie
d'accéder à une clef absente du dictionnaire. Dans le cas présent, la valeur de
la variable options
est assez évidente puisqu'elle se trouve quelques lignes
au-dessus dans le code source. Dans les programmes plus complexes, la valeur
d'une variable peut changer après un passage dans plusieurs fonctions, et c'est
très utile dans ces cas de pouvoir suivre son évolution.
Obtenir des information détaillées sur des objets
La valeur affichée par l'instruction print
est la représentation textuelle de
l'objet passé en paramètre, autrement dit la valeur retournée par la méthode
__str__
. Heureusement pour nous, le type dict
de Python définit cette
méthode, qui donne une représentation compréhensible de l'objet. Mais ce n'est
pas le cas pour tous les objets, notamment lorsque tu crées tes propres classes.
Pour voir ce que je veux dire, ouvre le fichier quiz_3.py
dans ton éditeur, et
ajoute une instruction print(question)
dans la boucle pour qu'elle ressemble
à ça :
for question in questions:
print(question)
# ...
Exécute maintenant le programme avec la commande python3 quiz_3.py
. Tu verras
apparaître l'information suivante :
<__main__.Question object at 0x7fdfd0afacab>
Ça nous fait une belle jambe, hein ? Heureusement, on peut examiner l'objet en détail
grâce aux fonctions dir
et vars
. Remplace l'instruction print
que tu viens
d'ajouter par les instructions suivantes :
for question in questions:
print(dir(question))
print(vars(question))
# ...
Si tu réexécutes ton programme, tu verras les informations suivantes s'afficher :
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_correct_answer',
'is_correct', 'label', 'options', 'points', 'show']
{'label': "Quelle est la vitesse de pointe d'un thon?",
'options': [<__main__.Option object at 0x7f98d3671c50>, <__main__.Option object at 0x7f98d3671c88>, <__main__.Option object at 0x7f98d3671cc0>],
'points': 3}
La première information, renvoyée par dir
, est la liste des attributs qui
existent sur l'objet. Tu y retrouveras aussi bien les méthodes
(get_correct_answer
, is_correct
, show
) que les propriétés (label
,
options
, points
). Les méthodes qui sont entourées de __
sont des méthodes
spéciales de
Python.
La fonction dir
est donc très pratique pour savoir comment utiliser un objet
puisqu'elle donne aussi bien la liste des méthodes qu'on peut utiliser sur
l'objet que ses propriétés.
La seconde information, renvoyée par vars
, est un dictionnaire qui représente
les propriétés qui existent sur l'objet. Les clefs de ce dictionnaire
représentent les noms des attributs (label
, options
, points
) et les valeurs
représentent les valeurs de ces attributs. La fonction vars
est donc très
pratique pour voir toutes les informations qu'un objet contient ainsi que leurs valeurs.
Note que si tu utilises cette technique pour débugger le code d'un site Django,
les valeurs affichées par print
apparaîtront dans le terminal dans lequel tu
as lancé le serveur Django, et pas sur la page web.
Pour aller plus loin
Tu sais maintenant comment utiliser les fonctions dir
et vars
pour examiner
des objets. Dans certains cas, tu préféreras interrompre le programme une fois la
valeur affichée. Pour cela tu peux remonter une exception avec la valeur que tu
veux examiner, par exemple en écrivant raise Exception(dir(question))
.
Néanmoins, cette façon de faire a ses limitations, parce qu'elle t'oblige à modifier ton code et réexécuter ton programme à chaque fois que tu veux examiner une variable différente. Pour les cas plus complexes, tu devrais plutôt utiliser PDB, le debugger Python, qui te permettra d'exécuter ton programme pas à pas et d'examiner les variables au fur et à mesure.
L'utilisation de PDB est expliquée en détail dans l'article « Débugger un programme Python ».
Tu veux en savoir plus ?
Génies du code est une méthode illustrée, adaptée à tous les niveaux, qui t'initiera à la programmation à travers la réalisation de ton propre site web de A à Z. Les deux premiers chapitres sont disponibles gratuitement dans leur intégralité !
Et aussi, fais un tour sur les autres articles, tous plus intéressants les uns que les autres, en toute modestie.