Sam & Max » debug http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Breakpoint conditionnels 3 http://sametmax.com/breakpoint-conditionnels/ http://sametmax.com/breakpoint-conditionnels/#comments Wed, 04 Nov 2015 06:56:11 +0000 http://sametmax.com/?p=16993 Quand vous lancez pdb, il est parfois intéressant stopper le programme à un endroit donné sous une certaine condition. En cela, on peut utiliser un if:

if truc:
    import pdb; pdb.set_trace()

Mais il est aussi possible de le faire pendant qu’on est en train d’utiliser le debugger grace à la commande “b” :

b 50, age == 18

Ceci va mettre un breakpoint à la ligne 50 qui s’activera uniquement si age vaut 18.

Des fois que ça serve…

]]>
http://sametmax.com/breakpoint-conditionnels/feed/ 3
Le debug par la force du Q 4 http://sametmax.com/le-debug-par-la-force-du-q/ http://sametmax.com/le-debug-par-la-force-du-q/#comments Sun, 04 Oct 2015 12:37:49 +0000 http://sametmax.com/?p=16944 print() puis du pdb... Puis le code se retrouve dans en background, ou on a des threads, des sous-processes, des proxies, son serveur WSGI qui tourne, etc. Et là, il faut sortir les outils de logging, la massue, le truc qui demande 3 ans à config.]]> D’abord ça commence avec des print() puis du pdb… Puis le code se retrouve en background, ou on a des threads, des sous-processes, des proxies, son serveur WSGI qui tourne, etc. Et là, il faut sortir les outils de logging, la massue, le truc qui demande 3 ans à config.

Il n’y a pas de juste milieu.

Alors un mec nous a donné son Q pour changer tout ça.

pip install q

Q est typiquement un lib de feignasse :

def bip():
    a = 1
 
    import q
    q(a)
    q(a + 1)
 
bip()

Et pouf, tout est loggé dans /tmp/q :

     0.0s bip: a=1
     0.0s bip: a + 1=2

On peut aussi l’utiliser en décorateur pour tracer l’exécution d’une fonction :

import q
 
@q
def bip():
    a = 1
bip()

Ce qui donne :

 0.0s bip()
 0.0s -> None

Ce n’est bien entendu pas fait pour être laissé dans le code, mais uniquement pour le debug. Néamoins c’est fort pratique :

  • Le fichier de log est setup automatiquement. On peut quand même choisir le dossier avec la variable d’environnement $TMPDIR
  • Le contenu de l’expression est logguée magiquement avec le résultat.
  • En prime on a le temps d’exécution.
  • Le fichier de sortie contient de la coloration syntaxique, s’il vous plait !

Avec Joe, qui génère des .gitignores, c’est ma petite découverte sympa de la rentrée.

]]>
http://sametmax.com/le-debug-par-la-force-du-q/feed/ 4
Lancer pdb dès qu’une exception a lieu 9 http://sametmax.com/lancer-pdb-des-quune-exception-a-lieu/ http://sametmax.com/lancer-pdb-des-quune-exception-a-lieu/#comments Fri, 10 Apr 2015 10:08:23 +0000 http://sametmax.com/?p=16055 Vous vous souvenez de excepthook et de pdb ?

Mélangeons les deux !

 
import sys
import traceback
import pdb
 
def pdb_post_mortem(exc_type, exc_val, exc_tb):
    # On affiche l'exception histoire de savoir ce qu'on debug
    print("".join(traceback.format_exception(exc_type, exc_val, exc_tb)))
    # On balance pdb en mode post mortem, c'est à dire qu'il va se lancer
    # malgré le fait que le programme ne marche plus, donnant accès
    # au contexte qu'il y avait juste avant que ça foire
    pdb.post_mortem(exc_tb)
 
# On dit à python de lancer cette fonction quand il plante
sys.excepthook = pdb_post_mortem
 
# On fait planter Python histoire de voir que ça marche bien
 
def boom():
    a = 1
    b = a / 0
boom()

Et si quand ça plante, Python nous pond la stack trace, puis nous lance un joli prompt de debugging qui donne accès à ce qu’on avait en mémoire just avant que la VM ne décède :

Traceback (most recent call last):
  File "test.py", line 16, in 
    boom()
  File "test.py", line 14, in boom
    b = a / 0
ZeroDivisionError: integer division or modulo by zero

> /home/sam/Bureau/test.py(14)test()
-> a = 1 / 0
(Pdb) 1
(Pdb) print a
1

C’est plus ou moins l’équivalent de lancer son programme manuellement avec :

python -m pdb programme.py

L’avantage de la première forme, c’est qu’on peut le setter et l’oublier, on faire une config un peu plus custom. L’avantage de la deuxième forme, c’est que c’est juste une ligne à taper, et en prime si on fait c, le programme redémarre automatiquement.

]]>
http://sametmax.com/lancer-pdb-des-quune-exception-a-lieu/feed/ 9
Mettre automatiquement DEBUG sur False en production pour Django 2 http://sametmax.com/mettre-automatiquement-debug-sur-false-en-production-pour-django/ http://sametmax.com/mettre-automatiquement-debug-sur-false-en-production-pour-django/#comments Sat, 01 Sep 2012 14:24:22 +0000 http://sametmax.com/?p=1913 L’avantage des fichiers de settings en pur Python, c’est qu’on peut faire des trucs mignons comme:

import socket
 
if socket.gethostname() == 'monsupersite.com':
    DEBUG = False
else:
    DEBUG = True
]]>
http://sametmax.com/mettre-automatiquement-debug-sur-false-en-production-pour-django/feed/ 2
Debugger en Python: les bases de pdb 4 http://sametmax.com/debugger-en-python-les-bases-de-pdb/ http://sametmax.com/debugger-en-python-les-bases-de-pdb/#comments Sun, 27 May 2012 04:40:05 +0000 http://sametmax.com/?p=750 Mettre une série de print dans son programme a ses limites, et python possède nativement une excellente alternative.

Pour la plupart des langages, on utilise un debugger intégré dans un IDE ou un programme à part. Ou alors on se contente de fonctions telles que var_dump ou print_r. En Python, on utilise le module pdb.

Quand vous voulez savoir ce qui se passe à un endroit du programme, à la ligne précise où vous souhaitez explorer le problème, ajoutez à votre code :

import pdb; pdb.set_trace()

Et relancez votre programme depuis une console.

L’exécution du programme va alors se figer, et dans la console vous aurez accès à un shell special:

(Pdb)

A quoi sert pdb

Dans ce shell vous pouvez entrer deux choses:

  • N’importe quelle expression Python qui tient sur une ligne.
  • Des commandes pdb speciales.

Ce qui est génial, c’est que toute expression Python sera éxécutée dans le context de la ligne où le programme s’est arrêté.

Donc vous pouvez faire des print, des if, des listes en intention, bref, tous les tests que vous voulez, avec les variables du programme dans l’état où elles sont à ce moment là.

Vous avez accès à tout le code, y compris vos propres objets, classes et fonctions. En fait, vous avez même accès à l’import, et donc à toutes les librairies importables.

L’essentiel des commandes

En plus de pouvoir exécuter du Python, vous pouvez utiliser des commandes. Il y en a des nombreuses, mais vous pouvez tirer l’essentiel de pdb avec six d’entre elles:

  •  l: Liste quelques lignes de code avant et après là où vous vous trouver. Utile pour se resituer dans le contexte du programme. ‘l’ pour ‘list’.
  •  n: Exécute la ligne suivante. Vous pouvez ainsi continuer l’exécution du programme de bout en bout, ligne par ligne, et le tester en entier. ‘n’ pour ‘next’.
  •  s: Si votre ligne contient un appel de fonction ou de méthode, rentre dans à l’intérieur. ‘s’ pour ‘step in’.
  •  r: Si vous êtes dans une fonction ou une méthode, celà permet d’en sortir et de passer dans le scope du dessus. ‘r’ pour ‘return’.
  • unt: Si vous êtes à la dernière ligne d’une boucle, permet de reprendre l’exécution jusqu’à la sortie de la boucle. ‘unt’ pour ‘until’.
  • q: Quitte brutalement le programme en le faisant crasher. ‘q’ pour ‘quit’.
  • c: Quitte le debugger et continue l’exécution du programme normalement. Tous les changements que vous avez fait dans le code sont pris en compte. ‘c’ pour ‘continue’.

Pour utiliser une commande, il suffit de taper la lettre et d’appuyer sur entrée. Si vous appuyez sur entrée sans rien saisir, la commande précédente est exécutée, ce qui vous évitera de spammer le shell de commandes n.

Les limites de pdb

  • Les commandes ont priorité sur le code Python. Vous ne pouvez donc pas assigner des variables dont le nom est en une seul lettre. C’est ennuyeux pour accéder à la variable ‘i‘ dans une boucle for. Dans ce cas, prefixez ‘i‘ par un ‘!‘ et il sera considéré comme du Python, et non comme une commande.
  • Si vous mettez set_trace dans une boucle, le debugger va se lancer à chaque tour de boucle, ce qui embrouille tout. Dans ce cas, et dans tous les cas où vous voulez que le debugger se lance à un moment particulier, utilisez un if ou un try/except pour que set_trace ne soit appelé que dans un cas précis.
  • Dans le cas de threads, de processus séparés, ou quand vous n’avez pas accès à stdout, pdb ne peut rien pour vous. Dans ce cas, le module logging est votre ami.

pdb + ipython = ipdb

Si vous êtes fan d’ipython, un coup de pip:

pip install ipdb

Et ensuite dans le programme:

import ipdb; ipdb.set_trace()

Vous aurez alors accès au shell de pdb, mais avec en prime les commandes et l’autocompletion d’ipython

Mettre un break point programmatiquement en javascript

Dans une moindre mesure, on peut aussi lancer un shell de debug depuis javascript. Ouvrez votre fenêtre d’outils Web intégrés au navigateur, Firebug ou équivalent.

Normalement il faut trouver votre script, puis la ligne, et mettre un break point.

Mais dans les navigateurs récents, vous pouvez juste ajouter:

debugger;

A la ligne voulue, et recharger la page. Votre outil de debuggage se mettra au break point automatiquement

]]>
http://sametmax.com/debugger-en-python-les-bases-de-pdb/feed/ 4