Aprende a hacer debug de tus programas en Python

Aprende a hacer debug de tus programas en Python

Introducción


Existen veces en las que estás escribiendo el código de algún script o un programa sencillo y no tan complejo, o tal vez no tan grande (aunque también funciona), o simplemente no necesitas un IDE completo para escribirlo. Y te encuentras con un error en tu código que no sabes el porqué está sucediendo, por más que intentas e intentas y no logras dar con el error, ni poniendo prints en tu código (no lo hagas o si lo haces no los dejes ahí).

Para ese problema es que existe un Debugger incorporado dentro de las librerías standard de Python el cual se llama PDB o Python Debugger AKA Depurador de Python en español.

Este pequeño pero sumamente aliado, nos ayudará a hacer un debug completo desde un sencillo script, hasta un proyecto ya más grande y robusto, además de que es muy interactivo. Aquí daremos una pequeña y sencilla explicación de como utilizarlo.

¿Qué es Python Debugger?


Para esto vamos a recurrir al sitio oficial de Python, en este caso en español y dice lo siguiente:

El modulo pdb define un depurador de código fuente interactivo para programas Python. Soporta el establecimiento de puntos de ruptura (condicionales) y pasos sencillos a nivel de línea de código fuente.

https://docs.python.org/es/3/library/pdb.html

Lo básico

Antes que podamos comenzar a utilizar nuestro debugger, primero debemos tener algún script o código para poder hacer debug, ya sea que este sea funcional o esté dando errores, incluso aunque funcione correctamente, puedes hacer debug para entender mejor como es que funciona y se ejecuta tu código.

Para esto, yo utilizaré un código sencillo que es una función de Fibonacci, el cual es muy corto y nos funciona perfecto para aprender lo básico e inspeccionar nuestro código.

def fib(n: int):
    a, b = 0, 1
    while a < n:
        print(a, end=" ")
        a, b = b, a+b
    print()

fib(1000)

Listo, ya tenemos nuestro código para probar pero… ¿Cómo lo probamos?, sencillo, importando e inicializando nuestro debugger.

import pdb; pdb.set_trace()

De esta manera, inicializamos nuestro debugger, cabe recalcar que al poner la linea de arriba al inicio de nuestro código, comenzará a inspeccionar el código desde el inicio así que si por ejemplo, tenemos un archivo de 100 líneas y queremos comenzar a inspeccionar apartir de la línea 52, entonces importamos pdb en la línea 51, para que comience desde ahí.

También, puedes importar pdb desde el inicio de tu archivo y, poner un breakpoint en la línea de código que desees inspeccionar.

En nuestro caso como es muy pequeño el código, podemos comenzar desde la línea 2, justo después de declarar la función.

def fib(n: int):
    import pdb; pdb.set_trace() # <-- comenzamos nuestro debugger
    a, b = 0, 1
    while a < n:
        print(a, end=" ")
        a, b = b, a+b
    print()

fib(1000)

Ahora sólo nos queda correr nuestro script y, veremos la mágia, como sobre la Terminal, nos apaceren las palabras (Pdb) y nos otorga un Prompt, sobre el cual podremos escribir y ejectutar comandos de pdb.

$ python fib.py
╰─$ /usr/bin/python /home/users/Documentos/projects/scripts/python/fib.py
> /home/user/Documentos/projects/scripts/python/fib.py(3)fib()
-> a, b = 0, 1
(Pdb) 

Ahora que tenemos algo como lo de arriba, quiere decir que nuestro programa detuvo la ejecución en la tercera línea del script, justo después de dónde importamos la librería.

Utilizando PDB


Crear un breakpoint

Los breakpoints se utilizan para decirle a nuestro debugger dónde queremos que se detenga o detenga la ejecución para poder revisar e inspeccionar de manera más detallada. Esto recibe como argumento un número entero, el cual será la línea en la cual deseamos detenerlo.

(Pdb) break 6

Y lo que nos regresa pdb debería ser algo como lo siguiente

Breakpoint 1 at /home/user/Documentos/projects/scripts/python/fib.py:6

Esto nos indica que el breakpoint número 1 fue creado en la línea 6 de nuestro archivo.

Reanudando la ejecución

Si en algún momento necesitamos reanudad la ejecución de nuestro script, entonces utilizamos la palabra continue

(Pdb) continue

Cabe recalcar que, si existe otro breakpoint, la ejecución se dentendrá hasta encontrarlo y si queremos seguir nuevamente damos continue.

Mostrando código cercano

Al estar utilizando la terminal únicamente como objeto de visualización de tu código, la interacción es muy pobre a la vista, y esto puede llevar a que te pierdas facilmente, para ello existe un comando que te permitirá mostrar las 11 lineas al rededor de la línea actual. El comando es list .

(Pdb) list
  1     def fib(n: int):
  2         import pdb; pdb.set_trace()
  3         a, b = 0, 1
  4         while a < n:
  5             print(a, end=" ")
  6 B->         a, b = b, a+b
  7 B       print()
  8  
  9     fib(1000)
[EOF]
(Pdb) 

Como puedes observar, te muestra en mi caso, el código completo ya que es muy corto, pero si fuese más grande, te mostraría únicamente las 11 líneas cercanas al punto detenido.

A su vez, te muestra con una B en la línea o lugar donde se encuentran los breakpoints, también podemos observar justamente el punto donde está detenida la ejecución con B->.

Avanzar paso por paso

Si lo que necesitas es avanzar línea por línea, también existe el argumento next , el cual nos permite avanzar al siguiente paso de ejecución, no el siguiente breakpoint, sino la siguiente línea que se ejecuta.

(Pdb) next
> /home/user/Documentos/projects/scripts/python/fib.py(4)fib()
-> while a < n:
(Pdb) next
> /home/user/Documentos/projects/scripts/python/fib.py(5)fib()
-> print(a, end=" ")
(Pdb) next
1 > /home/user/Documentos/projects/scripts/python/fib.py(6)fib()
-> a, b = b, a+b
(Pdb) next
> /home/user/Documentos/projects/scripts/python/fib.py(4)fib()
-> while a < n:

Cómo podemos observar, al utilizar next, vamos a ir paso por paso en cada momento de la ejecución del código, vamos de la línea 4 a la 5, después a la 6 y nuevamente a la 4 porque es una condición while que se sigue cumpliendo.

Inspeccionar Variables

Existe algo que nos puede ayudar demasiado y lo digo por experiencia, inspeccionar los valores que tienen las variables o el valor almacenado dentro de nuestras declaraciones, lo podemos observar con el argumento p <nombre_variable>.

(Pdb) p a
3
(Pdb) p b
5
(Pdb) 

Como podemos observar, tenemos nuestras dos variables definidas las cuales son a y b, que por defecto tienen 0 y 1 respectivamente. Al avanzar un poco el código, me detuve e inspeccioné ambas variables para observar el valor almacenado, que en este caso es 3 y 5.

Eliminar breakpoints

A veces también necesitamos eliminar breakpoints que ya no vamos a utilizar, para eso podemos borrar todos con el argumento clear .

(Pdb) clear
(Pdb) clear
Clear all breaks? y
Deleted breakpoint 1 at /home/users/Documentos/projects/scripts/python/fib.py:6
Deleted breakpoint 2 at /home/users/Documentos/projects/scripts/python/fib.py:7
(Pdb) 

Lo cual te pedirá la confirmación, en caso de querer eliminar todos le damos y o n en caso contrario.

Para eliminar un breakpoint en específico, hacemos lo mismo pero le pasamos el número del breakpoint como fue creado, por ejemplo si quiero eliminar el primero que creamos, entonces sería lo siguiente.

(Pdb) clear 1
Deleted breakpoint 1 at /home/user/Documentos/projects/scripts/python/fib.py:6
(Pdb) 

Y listo, esto es lo básico que debes conocer sobre el Python Debugger.

Conclusión


Con Pdb podrás inspeccionar tus programas o scripts de Python de una manera muy intuitiva y muy clara. Es una herramienta que te puede ayudar demasiado a encontrar algún error de ejecución o algún bug que se te pudo pasar, hacer debug es bueno, pero hacerlo bien es aún mejor.

Uno como desarrollador invierte mucho de su tiempo a encontrar y solucionar bugs y con esto, es posible aligerar mucho la carga y hacer nuestra vida más sencilla.