Explorando pdb++

PDB++ es una joya!

pdbpp es una alternativa avanzada al depurador pdb incorporado en Python. Es una extensión de pdb que agrega varias características útiles para la depuración de código Python, como el resaltado de sintaxis, autocompletado, modo interactivo (sticky) y mucho mas.

1
pip install pdbpp

Breakpoints

Codigo

Pon una de estas lineas donde quieras parar la ejecución:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# foo.py


def main():
  avar = 100
  bvar = 200
  import pdb; pdb.set_trace()
  # or
  breakpoint()
  out = avar + bvar
  return out

Para depurar, ejeucta:python foo.py

Interactivamente

Puedes usar el modulo pdb directamente: python -m pdb foo.py

(Pdb++) b <file>/<function>/<class>:<lineno>, <condition>
(Pdb++) b foo:6
(Pdb++) h # or help
(Pdb++) c # or continue

Usando .pdbrc

pdbpp lee automaticamente el archivo .pdbrc si existe lo que es muy comodo para tener tus breakpoints explicitos en un fichero y evitar modificar el codigo o tener que escribirlos cada vez en la consola:

nvim .pdbrc:

# .pdbrc
print("Hello from {__file__}")

Ejecuta: python foo.py

Esto permite tener un fichero por proyecto estandarizando el debugging, evitando por ejemplo modificar el codigo si no quieres. Compartiendo ese fichero otros pueden debuggear siguiendo el mismo patrón, etc.

También es posible definir un .pdbrc global creando un ~/.pdbrc. Todos los proyectos.

Configuración

Es posible cambiar la configuracion por defecto de pdbpp:

default .pdbrc.py

nvim ~/.pdbrc.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pdb


class Config(pdb.DefaultConfig):
    # default
    stdin_paste = 'epaste'
    filename_color = pdb.Color.lightgray
    use_terminal256formatter = False

    # custom
    prompt = ">>> "                        # Ready to copy as an example
    editor = 'nvim'                        # I love it, btw
    sticky_by_default = True               # Always shows the current long line first
    line_number_color = pdb.Color.darkred  # Use red line numbers
    truncate_long_lines = True             # Avoid ugly line wraps...
    enable_hidden_frames = True            # Show hidden frames by default
    exec_if_unfocused = None               # TODO: this is broken, open a issue.

    def setup(self, pdb):
        Pdb = pdb.__class__
        # Pdb.do_l = Pdb.do_longlist       # keep l as list (not long)
        Pdb.do_st = Pdb.do_sticky

Features favoritas

Función pdb.disable()

Omite los breakpoints que tengas en el codigo o en .pdbrc:

1
2
# .pdbrc / interectivamente
import pdb; pdb.disable()

Comando edit

En modo intercativo:

edit foo

Abre foo usando $EDITOR, require reiniciar el debugger para que tenga efecto.

Comando display

En modo intercativo / .pdbrc

display a

Cada vez que la variable a cambie se imprime el valor. Esto depende del scope en el que es ejecutado.

Decorador @pdb.break_on_setattr(attrname)

Breakpoint cuando cambia el atributo de una clase

1
2
3
4
5
6
# taken from https://github.com/pdbpp/pdbpp/tree/e1c2e347cc55a6dd89e058e56a1366ada68884bc
@break_on_setattr('bar')
class Foo(object):
    pass
f = Foo()
f.bar = 42    # the program breaks here

Esto es muy bueno!

Función pdb.xpm()

Extended post mortem:

1
2
3
4
try:
  foo() # raise an error
except Exception as e:
  pdb.xpm()

No he conseguido que funcione, pero me encanta la idea. A ver si consigo actualizar esto mas adelante.

Streaming

Este post es un resumen de lo que fui explorando en streaming: