¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Depurar un programa paso a paso

Después de esta lección: Puedo encontrar un error leyendo el mensaje y comprobando una cosa cada vez.

Lección de 60 min13 comandosLaboratorio de comandos de Linux de cada día: los treinta comandos que se escriben de memoria

Cómo depurar un programa que se equivoca

Depurar es averiguar por qué un programa hace algo mal y después cambiarlo. Casi todo el trabajo no es escribir la corrección. Es saber qué mirar entre cien cosas.

Adivinar y cambiar código al azar puede llevarte toda la tarde. Comprobar una cosa cada vez lleva unos minutos, y esta lección te enseña cómo.

Al terminar esta lección

Nota

Puedo encontrar un error leyendo el mensaje y comprobando una cosa cada vez.

Palabras clave

PalabraQué significa
Errorun fallo del programa que lo hace actuar mal
Reproducirhacer que el error ocurra otra vez, igual, cuando quieras
Tracebackla lista de llamadas que Python imprime cuando un programa se para con un error
Hipótesisuna idea sobre la causa que una sola comprobación puede refutar
Impresión de controluna línea que muestra un valor para ver lo que el programa guarda de verdad
Partir por la mitadcomprobar el medio de lo que queda, para descartar la mitad cada vez

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Primero haz que el error ocurra siempre

No puedes arreglar lo que no ves. Antes de cambiar nada, busca una entrada que provoque el error siempre, y guárdala.

Aquí un programa pequeño calcula el promedio de las ventas de un archivo, una línea por día. Sus datos tienen un hueco. Crea primero la carpeta y el archivo.

Crea una carpeta para la lección

Comando
mkdir -p ~/debugtest

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Entra en ella

Comando
cd ~/debugtest

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el archivo de ventas

Comando
printf 'lun 120\nmar 80\nmie n/d\njue 200\n' > sales.txt

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el programa del informe

Comando
printf 'def parse(line):\n    day, amount = line.split()\n    return day, int(amount)\n\n\ndef average(lines):\n    result = 0\n    for line in lines:\n        day, amount = parse(line)\n        result = result + amount\n    return result / len(lines)\n\n\nprint(average(open("sales.txt").read().splitlines()))\n' > report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo y mira cómo se para

Comando
python3 report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lee un traceback de abajo arriba

Un traceback lista las llamadas abiertas cuando el programa se paró. La llamada más nueva está abajo, así que lee desde abajo.

La última línea dice qué falló: ValueError, con un mensaje. La línea File de encima dice dónde: un archivo, un número de línea y una función. Las líneas anteriores dicen cómo llegó el programa allí.

Lista solo las líneas File

Comando
python3 report.py 2>&1 | grep "File"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Comprueba una cosa y luego la siguiente

El error muestra dónde se paró el programa, no por qué el dato era malo. Haz una hipótesis: una idea que una comprobación pueda refutar.

Aquí la idea es que una línea de datos no es un número. Busca en el archivo. Si no aparece nada, la idea era falsa, y eso también es avanzar.

Busca el texto en los datos

Comando
grep -n "n/d" sales.txt

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un arreglo rápido puede esconder otro error

La línea 3 dice mie n/d: ese día no hay cifra de ventas. Lo más rápido es contarlo como 0. Pruébalo y ejecuta el programa otra vez.

Cuenta una cifra que falta como 0

Comando
sed -i 's|    return day, int(amount)|    if amount == "n/d":\n        return day, 0\n    return day, int(amount)|' report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo otra vez

Comando
python3 report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Sin error no significa sin defecto

El programa se ejecutó e imprimió 100.0. Pero el promedio de los tres días con cifra, 120, 80 y 200, es 133,3 (Python lo escribe 133.3). El programa se equivoca y no dice nada.

Ahora no hay traceback que leer. Añade una impresión de control donde se suman los números y mira lo que guarda de verdad.

Imprime cada día al sumarlo

Comando
sed -i 's|        result = result + amount|        print(day, amount)\n        result = result + amount|' report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo y lee cada línea

Comando
python3 report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Parte el problema por la mitad

El programa tiene cuatro etapas. Comprueba primero la del medio. Si el total es correcto, el defecto está después. Si no, está antes. Cada comprobación descarta la mitad.

Así un equipo encuentra cuál de mil cambios rompió una función.

Ejemplo resuelto: comprobar las etapas

EtapaQué debería tenerQué teníaVeredicto
Leer el archivo4 líneas4 líneasBien
Leer cada cifra120, 80, n/d, 200120, 80, 0, 200El 0 es un número inventado
Sumar400400Bien
Dividir por los días contados400 / 3 = 133.3400 / 4 = 100.0Contó un día sin cifra

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Escribe el programa otra vez, con la corrección

Comando
printf 'def parse(line):\n    day, amount = line.split()\n    if not amount.isdigit():\n        return None\n    return day, int(amount)\n\n\ndef average(lines):\n    result = 0\n    count = 0\n    for line in lines:\n        pair = parse(line)\n        if pair is not None:\n            result = result + pair[1]\n            count = count + 1\n    return result / count\n\n\nprint(round(average(open("sales.txt").read().splitlines()), 1))\n' > report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecuta el programa corregido

Comando
python3 report.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cambia código antes de conocer la causa, y luego cambia otra cosa cuando falla. Tras cinco cambios nadie sabe cuál ayudó. Comprueba primero, cambia una cosa y ejecuta otra vez.

Más lejos: el cambio que lo rompió

Un equipo guarda cada cambio en Git. Cuando aparece un error, sabe que una versión antigua era buena y la más nueva es mala. La orden git bisect te pide probar la versión del medio y parte el historial hasta dejar un solo cambio.

Escribe los pasos para 1000 cambios. ¿Cuántas versiones pruebas como máximo?

Sobre este laboratorio y su código: Laboratorio de comandos de Linux de cada día: los treinta comandos que se escriben de memoria

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.