Errores y Excepciones en Python

Python distingue dos clases de error. Los de sintaxis impiden que el programa arranque. Las excepciones ocurren con el programa ya en marcha, y esas se pueden capturar y tratar.

Las que te vas a encontrar

CódigoExcepción y mensaje
100 * (200/0)ZeroDivisionError: division by zero
5 + variable_sin_definirNameError: name 'variable_sin_definir' is not defined
'suma_total' + 10TypeError: can only concatenate str (not "int") to str
int('hola')ValueError: invalid literal for int() with base 10: 'hola'
[1, 2][5]IndexError: list index out of range
{'a': 1}['b']KeyError: 'b'

Los mensajes son los que da Python 3.14 de verdad. Merece la pena leerlos enteros: casi siempre dicen exactamente qué pasó, y el nombre de la excepción dice de qué tipo es el problema.

try, except, else y finally

def leer_numero(texto):
    try:
        n = int(texto)
    except ValueError:
        print(f"{texto!r} no es un número")
        return None
    else:
        print(f"{texto!r} convertido sin problemas")
        return n
    finally:
        print("(esto se ejecuta siempre)")

leer_numero("42")
leer_numero("hola")
salida'42' convertido sin problemas
(esto se ejecuta siempre)
'hola' no es un número
(esto se ejecuta siempre)
BloqueCuándo se ejecuta
trysiempre: es el código que puede fallar
exceptsolo si salta esa excepción
elsesolo si no saltó ninguna
finallysiempre, haya fallo o no, y aunque haya un return por medio

El else parece que sobra, y no sobra: deja en el try solo la línea que puede fallar. Así un error inesperado en lo de después no se confunde con el que sí estabas esperando.

No uses except: sin nada detrás. La versión anterior de esta página lo hacía. Un except vacío captura todo: también un nombre mal escrito, que es un fallo tuyo, e incluso el Ctrl+C con el que intentas parar el programa. Captura siempre la excepción concreta que esperas.

Las excepciones traen información

try:
    open("no_existe.txt")
except FileNotFoundError as e:
    print("FileNotFoundError:", e.filename)
salidaFileNotFoundError: no_existe.txt

Crear las tuyas

class SaldoInsuficiente(Exception):
    def __init__(self, saldo, importe):
        super().__init__(f"saldo {saldo} € y quieres sacar {importe} €")
        self.saldo, self.importe = saldo, importe

try:
    raise SaldoInsuficiente(20, 50)
except SaldoInsuficiente as e:
    print("SaldoInsuficiente:", e, "| falta:", e.importe - e.saldo)
salidaSaldoInsuficiente: saldo 20 € y quieres sacar 50 € | falta: 30

Una excepción propia es una clase que hereda de Exception. Ventaja sobre lanzar una genérica: quien la captura puede distinguirla de las demás y sacar los datos que le hagan falta.

En la versión anterior, el ejemplo de raise NameError('Error inesperado') mostraba como salida NameError: HiThere. Era una salida copiada de la documentación oficial que no correspondía al código. Ahora todas las salidas de esta página salen de ejecutar el código que tienen encima.

Traducir una excepción sin perder la original

try:
    try:
        int("x")
    except ValueError as e:
        raise RuntimeError("no se pudo leer la configuración") from e
except RuntimeError as e:
    print("RuntimeError:", e, "| causa:", repr(e.__cause__))
salidaRuntimeError: no se pudo leer la configuración | causa: ValueError("invalid literal for int() with base 10: 'x'")

Con raise … from e lanzas un error con más sentido para quien te llama —«no se pudo leer la configuración»— y la causa original sigue enganchada. Si el programa termina, la traza muestra las dos.

Varias excepciones a la vez

try:
    raise ExceptionGroup("varios fallos", [ValueError("uno"), TypeError("dos")])
except* ValueError as g:
    print("except* ValueError:", [str(x) for x in g.exceptions])
except* TypeError as g:
    print("except* TypeError:", [str(x) for x in g.exceptions])
salidaexcept* ValueError: ['uno']
except* TypeError: ['dos']

Desde Python 3.11. Aparece cuando lanzas varias tareas en paralelo y fallan más de una: except*, con asterisco, recibe solo las de su tipo, y se ejecutan todos los que coincidan, no solo el primero.

Más información en inglés: Errors and exceptions in Python.

Todo el código se ejecutó con Python 3.14 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.