Pi-Python-PuDB

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche

Introduction

Programmer en Python c'est bien... pouvoir le faire en SSH c'est pratique mais que faire lorsque l'on a besoin de faire du débogage pour trouver d'où vient l'erreur?

Il y a deux techniques:

  1. Utiliser la fonction print() pour afficher des message dans la console (fonctionne aussi en ssh) se faire une idée de ce qui se passe dans le programme.
  2. Utiliser un programme de débogage (appelé debugger en anglais, débugger en français) qui permettra de suivre le programme pas à pas dans une interfacer aussi conviviale que possible.

Utilité d'un débugger

Le débugger est un programme spéciale qui peu prendre le contrôle de votre programme.

C'est pratique car cela permet d'exécuter votre programme ligne par ligne... et donc de le suivre à la trace tout en permettant d'explorer la valeur des variables et la pile d'appels (toutes les fonctions appelées avant celle que vous déboguez).

Il est également possible de placer des point d'arrêt (breakpoint en anglais) sur lesquels le débuggeur s'arrêtera avant l'exécution de cette ligne.

Une des particularité du débuggeur, c'est qu'il peut aussi resté en "veille" tant que votre programme fonctionne normalement et revenir en premier plan juste au moment ou l'erreur se produit (ou un breakpoint/point d'arrêt atteint).

C'est généralement le moment idéal pour investiguer un problème :-)

PuDB un débugger texte

Il y a probablement bon nombre de débuggeur sur le marché, tous avec leurs avantages et leurs inconvénients.

PuDB est plus intéressant dans le sens où il fonctionne en mode texte et en SSH! De surcroît il est facile a installer sur un Raspberry.

Vous pouvez donc prendre le contrôle un programme à distance et le débugger assez facilement avec un interface offrant une convivialité honorable (ce qui est loin d'être négligeable).

 

Vous pouvez également consulter ce screencast.

Installer PuDB

Si vous avez déjà préparé votre environnement Python (voir cet article), l'installation de PuDB sera une simple formalité.

sudo pip install pudb

Sur une version plus ancienne, vous pourriez avoir besoin d'utiliser easy_install :

sudo easy_install pudb

Faire du deboggage

Voici un petit exemple, pas à pas, expliquant comment faire du débogage.

Préparation de l'exemple

Pour illuster l'utilisation de PuDB, nous allons débogger le programme "raspi-button2.py" issu de ce tutoriel.

Comme l'utilisation de PuDB requière une petite modification du script, nous allons d'abord en faire une copie :-)

cp raspi-button2.py raspi-pudb.py

Ajouter set_trace()

Nous allons ensuite éditer le contenu de raspi-pudb.py pour activer de débogage.

nano raspi-pudb.py

Ci-dessous, nous avons repris les première lignes du programme Python.

#!/usr/bin/env python
# -*- coding: latin-1 -*-

# Exemple de debbogage basé sur raspi-button2.py en 
#   utilisant le debuggeur PuDB.
# http://pypi.python.org/pypi/pudb
#

import RPi.GPIO as GPIO, time
from pudb import set_trace

set_trace()

GPIO.setmode(GPIO.BCM)
GREEN_LED = 18
RED_LED = 23

BUTTON1 = 24
# Dernier état connu du bouton
# Par defaut: le bouton n'est pas considéré comme activé
BUTTON1_STATE = False

GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.setup(BUTTON1, GPIO.IN)
...

Démarrer le débuggeur

Pour commencer le débogage de votre programme, il faut démarrer votre script Python avec la commande suivante:

sudo python -m pudb raspi-pudb.py

Il est capital d'utiliser un sudo parce que le débuggeur doit pouvoir accéder à la mémoire du processus (dans /dev/mem ).

Au premier démarrage du débugger, vous serez invité à préciser vos préférences. Vous pouvez simplement vous déplacer sur le bouton [Ok] à l'aide de la flèche sur le clavier et accepter les paramètre en pressent la touche Entrée/Enter

Et voila!

 

Notez au passage la déclaration des variables (et leurs valeurs) en haut à droite.

Raccourcis clavier

PuDB se contrôle au clavier. Si cela paraît un peu "basic" c'est aussi terriblement efficace en ssh :-)

  • Ctrl-p : Editer/modifier les préférences
  • n : passer à la ligne suivante ("n" pour next signifiant suivant en anglais)
  • s : step into. S'applique aux appels de fonction. Le step into signifie que vous allez faire de l'exécution pas-à-pas dans la fonction plutôt que de simplement passer à la ligne suivante.
  • c : continuer l'exécution du programme jusqu'au prochain breakpoint/point d'arrêt (ou prochaine erreur)
  • r/f : finir l'exécution de la fonction ("r" correspondant à return signifiant retourner
  • t : exécuter jusqu'à la position du curseur.
  • e : Présente le traceback (liste des appel). Utilisable en cas d'exception ou mode post-mortem (quand votre programme est déclaré "mort" par Python)


  • H : Se déplacer vers la ligne courante (en bas de la pile, sur le point d'être exécuté)
  • u : Se déplacer vers l'appel de fonction précédent (move up one stack frame)
  • d : Se déplacer vers l'appel de fonction suivante... pour revenir au point de départ (move down one stack frame)


  • ! : Invoquer un shell python dans l'environnement actuel (également possible avec Ctrl-x).
    Sera bien utile pour inspecter des variables et leur contenu (en tapant leur nom dans le shell). Presser Ctrl-D pour revenir à la session de débogage.
  • o : Voir la console/écran de sortie
  • q : quitter le débugger


  • b : Activer/désactiver un point d'arrêt (breakpoint) sur lequel s'arrêtera le debugger.
  • m : ouvrir un module


  • j/k : haut/bas
  • ctrl-u/d : monter/descendre d'une page
  • h/l : déplacement a gauche/droite

Ressources

Toute référence, mention ou extrait de cette traduction doit être explicitement accompagné du texte suivant : «  Traduction par MCHobby (www.MCHobby.be) - Vente de kit et composants » avec un lien vers la source (donc cette page) et ce quelque soit le média utilisé.

L'utilisation commercial de la traduction (texte) et/ou réalisation, même partielle, pourrait être soumis à redevance. Dans tous les cas de figures, vous devez également obtenir l'accord du(des) détenteur initial des droits. Celui de MC Hobby s'arrêtant au travail de traduction proprement dit.