Depuración en Python. Aspectos generales (A3C34C2D02)

Introducción

En programación, la necesidad de la creación de código que funcione correctamente y sin errores siempre está presente como objetivo. En este contexto, la depuración se convierte en un aspecto esencial del proceso de programación. La depuración es un procedimiento sistemático que ayuda a detectar, aislar y rectificar errores o “bugs” en un programa, asegurando así tanto su correcto funcionamiento como la generación de un código libre de errores.

La habilidad para depurar programas en Python, al igual que en cualquier otro lenguaje de programación, es una competencia crucial para todo desarrollador. Un código correctamente depurado minimiza la existencia de errores sin detectar, previene fallos o comportamientos imprevistos del programa en su ejecución, y permite a los desarrolladores entender mejor la lógica y el flujo de su código, facilitando así el mantenimiento del software.

Entre las diversas herramientas disponibles para facilitar la depuración en Python, una de las más destacadas es pdb. Pdb, acrónimo de Python DeBugger, es el depurador integrado en el lenguaje Python. Este depurador brinda una serie de funcionalidades valiosas que permiten a los programadores recorrer su código paso a paso, inspeccionar variables y evaluar expresiones.

Tipos de errores

Al depurar programas en Python, es probable que nos encontremos con varios tipos de errores. Los errores en Python se clasifican generalmente en tres categorías: errores de sintaxis, excepciones y errores lógicos.

1 |  Errores de sintaxis: estos ocurren cuando el código viola las reglas de sintaxis del lenguaje Python. Ejemplos de este tipo de error podría ser desde olvidar poner dos puntos (:) al final de una declaración de función o clase, hasta errores de sangría o incluso omitir paréntesis o llaves. Cuando Python encuentra un error de sintaxis, interrumpe el proceso de interpretación de código y muestra un mensaje de error que indica la línea y la naturaleza del error.

2 |  Excepciones: estos son errores que ocurren durante la ejecución del programa. Aunque la sintaxis del código puede ser correcta, el programa puede generar un error cuando intenta ejecutar una instrucción. Las excepciones incluyen situaciones como intentar dividir un número por cero, abrir un archivo que no existe, o acceder a una variable no definida, entre otras. Python es muy explícito cuando se producen excepciones y proporciona un rastreo de pila detallado, incluyendo la línea en la que ocurrió la excepción y el tipo de excepción.

Atención

Un rastreo de pila en Python, también conocido como ‘stack trace’, es una representación de la secuencia de las llamadas de funciones que ha realizado tu programa hasta llegar a un punto determinado. Es como una huella digital de cómo tu programa ha llegado a donde está, generalmente presentado cuando ocurre un error. Si tu programa falla (un error), Python te mostrará la ‘ruta’ que siguió, indicando las funciones y métodos que se llamaron y en qué orden, para ayudarte a diagnosticar dónde pudo haber surgido el problema.

3 |  Errores lógicos: estos son los errores más difíciles de detectar y corregir. Los errores lógicos ocurren cuando la lógica o el diseño de un programa es incorrecto, pero el programa se ejecuta sin generar errores de sintaxis o excepciones. Un ejemplo común de un error lógico es un bucle infinito. Aunque el bucle puede ser sintácticamente correcto, si la condición de terminación del bucle nunca se cumple, el programa continuará ejecutándose indefinidamente. Estos errores no son capturados por el sistema de excepciones de Python, por lo que requieren una cuidadosa revisión del código y una comprensión sólida de la lógica del programa para su resolución.

Depurador pdb

El depurador pdb es una herramienta vital para el desarrollo de código en Python. Ofrece una gama de funcionalidades que facilitan el proceso de depuración, permitiendo a los desarrolladores rastrear su código, establecer puntos de ruptura, avanzar paso a paso, y mucho más. Aquí, revisaremos algunos de los conceptos clave para comenzar a depurar con pdb.

1 |  Puntos de ruptura: los puntos de ruptura son marcadores que puedes establecer en una línea de código específica donde quieres que la ejecución del programa se detenga. Esto es útil cuando sabes que un error ocurre en una sección específica del código, pero no estás seguro de exactamente dónde o por qué. Con pdb, puedes usar la función “set_trace()” para establecer un punto de ruptura.

2 |  Ejecución línea por línea: una vez que la ejecución del programa se ha detenido en un punto de ruptura, puedes usar la función “step” (o “s” en su forma abreviada) para avanzar línea por línea en el código.

3 |  Inspección de variables: al detenerse en un punto de ruptura o al avanzar línea por línea, puedes querer ver el valor de una variable específica. Con pdb, puedes hacerlo simplemente ingresando el nombre de la variable en la consola de pdb. También puedes usar la función “args” para ver los argumentos de la función actual.

4 |  Continuar la ejecución: si has detenido la ejecución en un punto de ruptura y has determinado que todo está funcionando correctamente hasta ese punto, puedes usar la función “continue” (o “c” en su forma abreviada) para reanudar la ejecución hasta el próximo punto de ruptura o hasta el final del programa.

5 |  Salir de pdb: si necesitas detener la depuración por cualquier motivo, puedes usar la función “quit” (o “q” en su forma abreviada) para salir de pdb y terminar la ejecución del programa.

Ejemplo de depuración de un programa

Partimos del siguiente código de ejemplo que divide un número por un denominador y luego decrementa el denominador hasta que llega a 0, lo que ocasionará una excepción del tipo ZeroDivisionError.

def division_decreciente(numerador, denominador):
    while denominador >= 0:
    resultado = numerador / denominador
        print(f”El resultado de dividir {numerador} entre {denominador} es {resultado}”)
        denominador -= 1

division_decreciente(10, 3)

Para depurar el código, vamos a insertar un punto de ruptura en la función antes de la línea que creemos que está causando el problema:

import pdb
def division_decreciente(numerador, denominador):
    while denominador >= 0:
        pdb.set_trace()
        resultado = numerador / denominador
        print(f”El resultado de dividir {numerador} entre {denominador} es {resultado}”)
        denominador -= 1

division_decreciente(10, 3)

Una posible simulación de la depuración en la consola de Python podría ser la siguiente:

      > python3 mi_programa.py
      
      > /ruta/a/mi_programa.py(6)division_decreciente()
      
      -> resultado = numerador / denominador
      
      (Pdb) p denominador
      
      3
      
      (Pdb) c
      
      El resultado de dividir 10 entre 3 es 3.3333333333333335
      
      > /ruta/a/mi_programa.py(6)division_decreciente()
      
      -> resultado = numerador / denominador
      
      (Pdb) p denominador
      
      2
      
      (Pdb) c
      
      El resultado de dividir 10 entre 2 es 5.0
      
      > /ruta/a/mi_programa.py(6)division_decreciente()
      
      -> resultado = numerador / denominador
      
      (Pdb) p denominador
      
      1
      
      (Pdb) c
      
      El resultado de dividir 10 entre 1 es 10.0
      
      > /ruta/a/mi_programa.py(6)division_decreciente()
      
      -> resultado = numerador / denominador
      
      (Pdb) p denominador
      
      0
      
      (Pdb) s
      
      ZeroDivisionError: division by zero
       

En esta simulación, utilizamos el comando “p” para inspeccionar el valor del denominador en cada iteración del bucle. También utilizamos el comando “c” para continuar la ejecución hasta el próximo punto de ruptura, que está dentro del bucle, por lo que se detiene en cada iteración. Finalmente, cuando vemos que el denominador es 0, utilizamos el comando “s” para avanzar a la línea siguiente, lo que provoca el ZeroDivisionError. Mediante la depuración, el programador podría percatarse de la línea en la que se está produciendo el error y justo la situación que lo provoca (valores concretos de numerador y denominador).

Saber más

Puedes aplicar tus conocimientos en depuración en Python con pdb a través de la documentación oficial de Python en castellano, en concreto, en e.digitall.org.es/depuracion