Última actualización: 04 de diciembre de 2023

6.1. Depuración con pdb

En este tutorial se exploran herramientas que ayudan a entender tu código: depuración para encontrar y corregir bugs (errores).

El depurador python, pdb, te permite inspeccionar tu código de forma interactiva.

Te permite:

  • Ver el código fuente.

  • Ir hacia arriba y hacia abajo del punto donde se ha producido un error.

  • Inspeccionar valores de variables.

  • Modificar valores de variables.

  • Establecer breakpoints (punto de parada del proceso).

6.1.1. Invocando al depurador

Formas de lanzar el depurador:

  1. Postmortem, lanza el depurador después de que se hayan producido errores.

  2. Lanza el módulo con el depurador.

  3. Llama al depurador desde dentro del módulo.

6.1.1.1. Postmortem

Situación: Estás trabajando en ipython y obtienes un error (traceback).

En este caso esta depurando el archivo index_error.py. Cuando lo ejecutes verás como se lanza una excepción IndexError. Escribe %debug y entrarás en el depurador.

In [1]: %run index_error.py
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
/home/macagua/python/entrenamiento/index_error.py in <module>()
      6
      7 if __name__ == '__main__':
----> 8     index_error()
      9

/home/macagua/python/entrenamiento/index_error.py in index_error()
      3 def index_error():
      4     lst = list('foobar')
----> 5     print(lst[len(lst)])
      6
      7 if __name__ == '__main__':

IndexError: list index out of range

In [2]: %debug
> /home/macagua/python/entrenamiento/index_error.py(5)index_error()
      4     lst = list('foobar')
----> 5     print(lst[len(lst)])
      6

ipdb> list
      1 """Small snippet to raise an IndexError."""
      2
      3 def index_error():
      4     lst = list('foobar')
----> 5     print(lst[len(lst)])
      6
      7 if __name__ == '__main__':
      8     index_error()
      9

ipdb> len(lst)
6
ipdb> print(lst[len(lst)-1])
r
ipdb> quit

In [3]:

6.1.1.2. Ejecución paso a paso

Situación: Crees que existe un error en un módulo pero no estás seguro donde.

Por ejemplo, esta intentado depurar wiener_filtering.py. A pesar de que el código se ejecuta, observa que el filtrado no se está haciendo correctamente.

  • Ejecuta el script en IPython con el depurador usando %run -d wiener_filtering.py:

    In [1]: %run -d wiener_filtering.py
    *** Blank or comment
    *** Blank or comment
    *** Blank or comment
    Breakpoint 1 at /home/macagua/python/entrenamiento/wiener_filtering.py:4
    NOTE: Enter 'c' at the ipdb>  prompt to start your script.
    > <string>(1)<module>()
    
  • Coloca un breakpoint en la línea 34 usando b 34:

    ipdb> n
    > /home/macagua/python/entrenamiento/wiener_filtering.py(4)<module>()
          3
    1---> 4 import numpy as np
          5 import scipy as sp
    
    ipdb> b 34
    Breakpoint 2 at /home/macagua/python/entrenamiento/wiener_filtering.py:34
    
  • Continua la ejecución hasta el siguiente breakpoint con c(ont(inue)):

    ipdb> c
    > /home/macagua/python/entrenamiento/wiener_filtering.py(34)iterated_wiener()
         33     """
    2--> 34     noisy_img = noisy_img
         35     denoised_img = local_mean(noisy_img, size=size)
    
  • Da pasos hacia adelante y detrás del código con n(ext) y s(tep). next salta hasta la siguiente declaración en el actual contexto de ejecución mientras que step se moverá entre los contextos en ejecución, i.e. permitiendo explorar dentro de llamadas a funciones:

    ipdb> s
    > /home/macagua/python/entrenamiento/wiener_filtering.py(35)iterated_wiener()
    2    34     noisy_img = noisy_img
    ---> 35     denoised_img = local_mean(noisy_img, size=size)
         36     l_var = local_var(noisy_img, size=size)
    
    ipdb> n
    > /home/macagua/python/entrenamiento/wiener_filtering.py(36)iterated_wiener()
         35     denoised_img = local_mean(noisy_img, size=size)
    ---> 36     l_var = local_var(noisy_img, size=size)
         37     for i in range(3):
    
  • Muévete unas pocas líneas y explora las variables locales:

    ipdb> n
    > /home/macagua/python/entrenamiento/wiener_filtering.py(37)iterated_wiener()
         36     l_var = local_var(noisy_img, size=size)
    ---> 37     for i in range(3):
         38         res = noisy_img - denoised_img
    ipdb> print(l_var)
    [[5868 5379 5316 ..., 5071 4799 5149]
     [5013  363  437 ...,  346  262 4355]
     [5379  410  344 ...,  392  604 3377]
     ...,
     [ 435  362  308 ...,  275  198 1632]
     [ 548  392  290 ...,  248  263 1653]
     [ 466  789  736 ..., 1835 1725 1940]]
    ipdb> print(l_var.min())
    0
    

Oh dear, solo ve entero y variación 0. Aquí está nuestro error, estamos haciendo aritmética con enteros.

6.1.1.3. Otras formas de comenzar una depuración

  • Lanzar una excepción «break point» a lo pobre

    Si encuentras tedioso el tener que anotar el número de línea para colocar un break point, puedes lanzar una excepción en el punto que quieres inspeccionar y usar la “magia” %debug de ipython. Destacar que en este caso no puedes moverte por el código y continuar después la ejecución.

  • Depurando fallos de pruebas usando nosetests

    Puede ejecutar nosetests --pdb para saltar a la depuración post-mortem de excepciones y nosetests --pdb-failure para inspeccionar los fallos de pruebas usando el depurador.

    Además, puedes usar la interfaz IPython para el depurador en nose usando el plugin de nose ipdbplugin. Puede, entonces, pasar las opciones --ipdb y --ipdb-failure a los nosetests.

  • Llamando explícitamente al depurador

    Inserta la siguiente línea donde quieres que salte el depurador:

    1
    2
    3
      import pdb
    
      pdb.set_trace()
    

Advertencia

Cuando se ejecutan nosetests, se captura la salida y parecerá que el depurador no está funcionando. Para evitar esto simplemente ejecuta los nosetests con la etiqueta -s.

6.1.2. Comandos del depurador e interacciones

l(list)

Lista el código en la posición actual

u(p)

Paso arriba de la llamada a la pila (call stack)

d(own)

Paso abajo de la llamada a la pila ((call stack)

n(ext)

Ejecuta la siguiente línea (no va hacia abajo en funciones nuevas)

s(tep)

Ejecuta la siguiente declaración (va hacia abajo en las nuevas funciones)

bt

Muestra el call stack

a

Muestra las variables locales

!command

Ejecuta el comando Python proporcionado (en oposición a comandos pdb)

Advertencia

Los comandos de depuración no son código Python

No puedes nombrar a las variables de la forma que quieras. Por ejemplo, si esta dentro del depurador no podrá sobrescribir a las variables con el mismo y, por tanto, habrá que usar diferentes nombres para las variables cuando este tecleando código en el depurador.

6.1.3. Obteniendo ayuda dentro del depurador

Teclea h o help para acceder a la ayuda interactiva:

ipdb> help

Documented commands (type help <topic>):
========================================
EOF    bt         cont      enable  jump  pdef   r        tbreak   w
a      c          continue  exit    l     pdoc   restart  u        whatis
alias  cl         d         h       list  pinfo  return   unalias  where
args   clear      debug     help    n     pp     run      unt
b      commands   disable   ignore  next  q      s        until
break  condition  down      j       p     quit   step     up

Miscellaneous help topics:
==========================
exec  pdb

Undocumented commands:
======================
retval  rv

Importante

Usted puede descargar el código usado en esta sección haciendo clic en los siguientes enlaces: index_error.py y wiener_filtering.py. Adicional se incluye otro código de ejemplo muy simple funcion_a_depurar.py usando la función set_trace() del paquete pdb.

Truco

Para ejecutar el código index_error.py, wiener_filtering.py y funcion_a_depurar.py, abra una consola de comando, acceda al directorio donde se encuentra ambos programas:

leccion6/
├── index_error.py
├── wiener_filtering.py
└── funcion_a_depurar.py

Si tiene la estructura de archivo previa, entonces ejecute por separado cada comando:

$ python index_error.py
$ python wiener_filtering.py
$ python funcion_a_depurar.py

Ver también

Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.


¿Cómo puedo ayudar?

¡Mi soporte está aquí para ayudar!

Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. GMT-4 - Caracas, Venezuela.

La hora aquí es actualmente 7:35 PM GMT-4.

Mi objetivo es responder a todos los mensajes dentro de un día hábil.

Contrata mi increíble soporte profesional