Menu

Tipos de error en Python y depuración: leer tracebacks y arreglar errores comunes

Un recorrido por los errores de Python que te encontrarás más a menudo — KeyError, ValueError, ModuleNotFoundError, EOFError — y los hábitos de depuración que los arreglan rápido.

Los errores son cómo Python te dice qué pasó

Cada error de Python es un objeto con un tipo, un mensaje y un traceback — la cadena de llamadas que llevó hasta él. Leer uno bien es la habilidad de depuración más importante que puedes coger. Esta página es un recorrido por los errores con los que de verdad te encontrarás, y los hábitos que hacen que arreglarlos sea rápido.

Para una mirada más profunda a la mecánica de try/except y lanzar los tuyos, la página de Excepciones cubre la sintaxis. Esta página va sobre los errores específicos y cómo leerlos.

Leer un traceback

Ejecuta algo que se rompa:

def divide(a, b):
    return a / b

def report(values):
    for v in values:
        print(divide(10, v))

report([5, 2, 0])

Python imprime algo como:

Traceback (most recent call last):
  File "script.py", line 8, in <module>
    report([5, 2, 0])
  File "script.py", line 6, in report
    print(divide(10, v))
  File "script.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero

Lee esto de abajo arriba:

  1. ZeroDivisionError: division by zero — el tipo de excepción y el mensaje. Esto es qué fue mal.
  2. return a / b en divide, línea 2 — la línea que realmente lanzó.
  3. print(divide(10, v)) en report, línea 6 — la llamada que lo disparó.
  4. report([5, 2, 0]) a nivel de módulo, línea 8 — donde empezó.

El frame de abajo es casi siempre donde va el arreglo. Cuando una librería lanza un error en lo profundo de sus entrañas, sube por el traceback hasta el primer frame en tu código — esa es la llamada a la que pasaste mala entrada.

Los errores con los que te encontrarás más a menudo

NameError

main.py
Output
Click Run to see the output here.

"Name 'mesage' is not defined". Causado por typos o por usar una variable antes de asignarla. El mensaje de error de Python normalmente sugiere un reemplazo probable en versiones recientes ("Did you mean 'message'?").

Arreglo: comprueba la ortografía y el ámbito. Si el nombre solo existe dentro de una función, no puedes leerlo desde fuera.

TypeError

main.py
Output
Click Run to see the output here.

"Can only concatenate str (not 'int') to str". Tipo equivocado para la operación. Clásicos: sumar un string a un número, llamar a algo que no es callable, pasar el número de argumentos equivocado a una función.

Arreglo: convierte tipos explícitamente (str(30), int("30")) o inspecciona lo que estás pasando realmente. Una f-string suele leerse mejor que la concatenación con + entre tipos: f"age: {30}".

ValueError

main.py
Output
Click Run to see the output here.

"Invalid literal for int() with base 10: 'hello'". El tipo está bien — int() acepta un string — pero el valor no encaja. Común con int(), float(), parseo de datetime y funciones que toman un argumento acotado.

Arreglo: valida antes de convertir, o captura el error y manéjalo:

main.py
Output
Click Run to see the output here.

KeyError

main.py
Output
Click Run to see the output here.

"KeyError: 'charlie'". La clave no está en el dict. Tres arreglos idiomáticos, elegidos por intención:

main.py
Output
Click Run to see the output here.

Para un dict donde las claves que faltan deberían auto-inicializarse, collections.defaultdict merece un vistazo.

IndexError

main.py
Output
Click Run to see the output here.

"List index out of range". Pediste una posición que la secuencia no tiene.

Arreglo: protege con una comprobación de longitud, usa -1 para referenciar el último elemento, o usa slicing (numbers[5:6] devuelve [] en vez de lanzar).

AttributeError

main.py
Output
Click Run to see the output here.

"'NoneType' object has no attribute 'upper'". Llamaste a un método sobre algo que no lo tiene. Casi siempre significa que una variable es un tipo inesperado — a menudo None cuando esperabas un valor real.

Arreglo: averigua de dónde vino el None. print(type(var)) o un breakpoint justo antes del error es la forma más rápida. Las funciones que "a veces fallan" normalmente devuelven None; comprueba su valor de retorno antes de llamar a métodos sobre él.

ModuleNotFoundError (y ImportError)

import fastapi

"No module named 'fastapi'". El paquete no está instalado en el intérprete de Python que tu script está usando. Dos causas comunes:

  1. Realmente no lo has instalado. Ejecuta python -m pip install fastapi en el entorno correcto.
  2. Lo instalaste, pero en un Python distinto. Pasa constantemente en macOS cuando pip y python apuntan a instalaciones distintas.

El arreglo fiable es instalar con el mismo intérprete con el que ejecutas:

python -m pip install fastapi

Si usas un entorno virtual (y deberías), asegúrate de que esté activado antes tanto de pip install como de python script.py.

FileNotFoundError

with open("settings.yaml") as f:
    config = f.read()

"[Errno 2] No such file or directory: 'settings.yaml'". La ruta no existe relativa a donde sea que el script esté corriendo.

Arreglo: imprime os.getcwd() al principio del script para confirmar dónde está mirando Python. Usa rutas absolutas o pathlib.Path(__file__).parent / "settings.yaml" para anclar rutas a la ubicación del propio script.

EOFError

name = input("Name: ")

"EOF when reading a line". input() intentó leer desde stdin y no obtuvo nada — o la entrada se pipeó desde una fuente vacía, o pulsaste Ctrl-D en el prompt.

Arreglo: si piping es legítimo, envuelve la llamada:

try:
    name = input("Name: ")
except EOFError:
    name = "anonymous"

En el editor en el navegador de estos docs, el runtime simula la entrada; no te topas con esto ahí.

IndentationError y SyntaxError

IndentationError: expected an indented block after function definition on line 2

Estos son especiales — disparan antes de que tu programa se ejecute. Python rechazó parsear el archivo.

  • IndentationError — el cuerpo de un def, if, for, etc. falta o está mal alineado. La mayoría de editores visualizan la indentación; activa "show whitespace" para cazar tabs y espacios mezclados.
  • SyntaxError — olvidaste dos puntos, desequilibraste un paréntesis o escribiste mal una palabra clave. Las versiones recientes de Python apuntan con una flecha (^) al carácter ofensor.

Arreglo: el mensaje de error nombra la línea. Ve a mirar. Si nada está obviamente mal en esa línea, comprueba la línea anterior — un paréntesis sin cerrar unas líneas arriba a menudo se muestra como error de sintaxis mucho después.

RuntimeError

Un cajón de sastre para "algo fue mal en runtime que no es uno de los errores más específicos". RecursionError (excedió la profundidad de recursión) es una especialización común. El código de librerías a menudo lanza RuntimeError cuando está en un mal estado.

Arreglo: lee el mensaje; suele ser descriptivo. Si la recursión es la causa, o conviértelo a un bucle iterativo o sube sys.setrecursionlimit en casos raros.

Depuración con print

Antes de recurrir a un debugger real, print() — o mejor, la forma f"{var=}" — caza la mayoría de bugs:

main.py
Output
Click Run to see the output here.

f"{var=}" imprime tanto el código fuente de la expresión como su valor, así que no tienes que reescribir el nombre en el string de formato. Ejecuta el script, escanea la salida, encuentra la línea donde un valor se volvió incorrecto. La mayoría de bugs "misteriosos" se vuelven obvios tras tres o cuatro prints bien colocados.

Limpia los prints antes de hacer commit. logging.debug(...) es más agradable que print para código que vas a enviar — puedes encender y apagar el logging de depuración sin editar líneas.

breakpoint() y pdb

Cuando print no basta, breakpoint() te mete en el debugger interactivo de Python en ese punto:

def discount(price, percent):
    breakpoint()
    return price * (1 - percent / 100)

discount(100, 20)

Ejecuta el script en una terminal real. Aterrizarás en un prompt (Pdb). Unos cuantos comandos que conocer:

  • p variable — imprime una variable.
  • n — pasa a la siguiente línea.
  • s — entra en una llamada a función.
  • c — continúa ejecutando hasta el siguiente breakpoint o el final.
  • q — salir.
  • l — lista el código fuente alrededor de la línea actual.

Los debuggers de IDE (VS Code, PyCharm) envuelven el mismo protocolo en una GUI — breakpoints puestos en el margen, una barra lateral mostrando variables. Elige el que se sienta de menor fricción.

Hábitos que reducen los errores con los que te encuentras

  • Usa nombres descriptivos para las variables. La mitad del ruido de TypeError y AttributeError desaparece cuando no puedes olvidar qué hay en una variable.
  • Valida entradas en la frontera. Parsea y comprueba entrada de usuario / contenido de archivos una vez, al principio de la función. El resto del código puede entonces confiar en los valores.
  • Falla ruidosamente, no silenciosamente. Un except Exception: pass a secas oculta los errores que realmente necesitas ver. Captura excepciones específicas, manéjalas deliberadamente y deja que el resto se propague.
  • Lee el final del traceback primero. Cada minuto gastado aprendiendo a leer tracebacks se paga cien veces.

La mayoría de errores no son misterios — son typos de una línea o errores de tipo equivocado con un mensaje claro. Confía en el mensaje de error; normalmente tiene razón.

Has llegado

Ese es el final de la sección de referencia. Has ido desde "¿qué es Python?" pasando por variables, flujo de control, colecciones, funciones, clases, iteración, datos del mundo real y errores. Desde aquí los siguientes pasos tienen forma de proyecto: elige algo que quieras construir y trabaja hacia atrás hasta las piezas que necesites aprender con más profundidad. Estas páginas seguirán aquí cuando vuelvas con una pregunta específica.

Preguntas frecuentes

¿Qué es un KeyError en Python?

KeyError se lanza cuando buscas una clave de dict que no existe. users["missing"] lanza KeyError: 'missing'. Las alternativas seguras son users.get("missing", default), users.get("missing") (devuelve None) o una comprobación explícita if key in users:.

¿Qué es un EOFError en Python?

EOFError (end-of-file) se lanza cuando input() no puede leer nada porque el stream de entrada se cerró. Lo verás más a menudo cuando un script que usa input() se pipea sin datos, o cuando pulsas Ctrl-D en el prompt interactivo. Protege con try/except EOFError si tu script debe manejar entrada pipeada.

¿Qué es un ModuleNotFoundError?

ModuleNotFoundError significa que import X no encontró un módulo llamado X. O el paquete no está instalado (pip install X), o está instalado en un Python distinto del que está ejecutando tu código (muy común cuando tienes varios Pythons). python -m pip install X arregla el segundo caso usando el mismo intérprete.

¿Cómo leo un traceback de Python?

Léelo de abajo arriba. La última línea es el tipo y mensaje de excepción — la cosa específica que fue mal. Las líneas de arriba muestran la pila de llamadas que llevó hasta ahí, con tu propio código normalmente más cerca del final. Haz clic o salta al archivo + línea en el frame más abajo que sea tuyo; ahí va el arreglo.

Aprende a programar con Coddy

COMENZAR