Annexe C — Trouver les bugs avec Spyder
Il est extrêmement rare d’écrire un code juste du premier coup. Au-delà des erreurs de syntaxe, de compatibilité, de taille entre les tableaux, ou autres erreurs qui se manifestent par une exception qui arrête l’exécution du programme, il peut y avoir des bugs qui n’empêchent pas le programme de tourner, mais ce dernier ne calcule pas ce qu’il devrait calculer correctement.
Spyder dispose d’outils qu’il est important de connaître pour pouvoir facilement trouver ces bugs. Dans ce court article, nous allons apprendre à nous servir de ces outils pour trouver un bug typique d’un programme de calcul scientifique.
C.1 Le programme
Voici le programme que l’on va déboguer :
# -*- coding: utf-8 -*-
= 0.
position = 1.
vitesse = 1.
masses
= 100
n_pas = 0.1
dt
def gravite(position):
return -1
= gravite(position)
force
for i in range(n_pas):
+= force * dt / 2
vitesse += dt * vitesse
position += gravite(position)
force += force * dt / 2
vitesse
= n_pas * dt
t_final = 0.5 * (-1) * t_final**2 + 1. * t_final
position_analytique
# On vérifie que la position finale et la solution analytique sont identiques
assert abs(position - position_analytique) < 1e-10, "Positions différentes !"
Exécutez le programme. Ce dernier doit générer un message d’erreur dans la console :
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
File ~/Documents/repos/projets-numeriques-discrets/book/data/bugs.py:26
23 position_analytique = 0.5 * (-1) * t_final**2 + 1. * t_final
25 # On vérifie que la position finale et la solution analytique sont identiques
---> 26 assert abs(position - position_analytique) < 1e-10, "Positions différentes !"
AssertionError: Positions différentes !
Ce message d’erreur indique la nature de l’erreur (AssertionError
), la raison (Positions différentes !
), ainsi que l’endroit où se produit l’erreur (File ~/Documents/repos/projets-numeriques-discrets/book/data/bugs.py:26
, qui est la ligne 26). Cliquez sur ligne File: ...
pour aller directement à l’endroit de l’erreur.
Ici, on a utilisé la directive assert
pour générer une erreur si les deux positions position
et position_analytique
sont différentes. Il y a donc un problème avec notre implémentation de l’algorithme d’intégration en temps (Velocity-Verlet).
C.2 Inspection des variables
Spyder dispose d’un inspecteur de variable, qui permet de facilement voir la valeur des variables au moment ou le programme s’arrête. On remarque ici que la position finale est -1706.5
, très différente de la position analytique de -40
, d’où l’erreur lors de l’assertion.
On peut aussi inspecter les autres variables, qui indiquent des valeurs a priori élevées de la force et de la vitesse.
L’inspecteur des variables indique aussi la taille des tableaux Numpy, ce qui est très utile pour vérifier que les tableaux de position, vitesse, etc., ont des tailles compatibles.
C.3 Déboguer un script Python
Le désavantage de l’inspecteur de variables est qu’il n’indique que l’état des variables au moment de l’arrêt du programme. Un débogueur est un programme qui permet de contrôler l’exécution d’un script, ce qui permet de connaître la valeur des variables à tout moment de l’exécution du programme, et donc facilite la vie du programmeur ou de la programmeuse.
Dans Spyder, il est possible de sélectionner des lignes de code où le débogueur doit arrêter l’exécution du code : c’est un point d’arrêt, ou breakpoint en anglais. Il suffit de cliquer entre la ligne de code et le numéro de la ligne dans l’interface : un petit cercle rouge doit apparaître sous le curseur de la souris.
Une fois un breakpoint posé, il faut lancer le débogueur. Pour cela, on peut cliquer le bouton “Déboguer le script”, raccourci Ctrl+F5
. Le script est alors lancé jusqu’à ce que l’exécution atteigne le premier breakpoint.
À ce moment, l’inspecteur de variables affiche les valeurs des variables au breakpoint. Pour avancer l’exécution, on peut cliquer sur le bouton à droite entouré de rouge ci-dessus (en anglais “Debug current line”, raccourci Ctrl+F10
), qui avance d’une ligne. On peut ainsi observer les changements dans les valeurs des variables. On peut également cliquer sur le bouton “Continuer l’exécution jusqu’au prochain point d’arrêt” (raccourci Ctrl+F12
), qui avance l’exécution jusqu’au prochain breakpoint, ce qui est pratique dans les boucles.
On peut à tout moment arrêter le débogage avec le bouton approprié (ou Ctrl+Maj+F12
).
Servez-vous du débogueur pour observer l’évolution de la force dans la boucle for
. Corrigez le bug.