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 -*-
position = 0.
vitesse = 1.
masses = 1.

n_pas = 100
dt = 0.1


def gravite(position):
    return -1

force = gravite(position)

for i in range(n_pas):
    vitesse += force * dt / 2
    position += dt * vitesse
    force += gravite(position)
    vitesse += force * dt / 2


t_final = n_pas * dt
position_analytique = 0.5 * (-1) * t_final**2 + 1. * t_final

# On vérifie que la position finale et la solution analytique sont identiques
assert abs(position - position_analytique) < 1e-10, "Positions différentes !"
Consigne

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

Inspecteur 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.

Astuce

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.

Vue en mode debug. Le point rouge est un breakpoint, la flèche bleue indique la ligne où est le débogueur.

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.

Boutons de contrôle du débogueur (en bleu). Entourés de rouge sont les boutons pour déboguer de fichier et passer à la ligne suivante.

À 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).

Consigne

Servez-vous du débogueur pour observer l’évolution de la force dans la boucle for. Corrigez le bug.