Excepciones en Python

Aprendé a manejar errores de forma elegante con try, except, else y finally. Los errores son parte del software — lo importante es saber cómo tratarlos.

¿Qué es una excepción?

Cuando Python encuentra un error en tiempo de ejecución, lanza una excepción. Si no la manejás, el programa se detiene con un mensaje de error.

# Sin manejo de errores — el programa explota
numero = int("hola")   # ValueError
lista  = [1, 2, 3]
print(lista[10])       # IndexError
resultado = 10 / 0    # ZeroDivisionError

Con try / except podés atrapar esas excepciones y decidir qué hacer.

try:
    numero = int("hola")
except ValueError:
    print("Eso no es un número válido")
Errores vs Excepciones

En Python, los errores de sintaxis (SyntaxError) ocurren antes de ejecutar el código. Las excepciones ocurren durante la ejecución. El bloque try/except solo maneja excepciones, no errores de sintaxis.

Probá el Ejemplo 1: except básico

Estructura completa: try / except / else / finally

try:
    # Código que puede fallar
    resultado = 10 / 2

except ZeroDivisionError:
    # Se ejecuta si ocurre ese error específico
    print("No se puede dividir por cero")

else:
    # Se ejecuta si NO hubo ninguna excepción
    print(f"Resultado: {resultado}")

finally:
    # Se ejecuta SIEMPRE, haya error o no
    print("Operación finalizada")

try

Código que puede fallar

Si falla, salta al except

except

Manejar el error

Se ejecuta si hubo excepción

else

Todo salió bien

Solo si no hubo excepción

finally

Siempre se ejecuta

Ideal para liberar recursos

Probá el Ejemplo 2: estructura completa

Excepciones más comunes

ExcepciónCuándo ocurreEjemplo
ValueErrorValor incorrecto para la operaciónint("hola")
TypeErrorTipo de dato incorrecto"2" + 2
ZeroDivisionErrorDivisión por cero10 / 0
IndexErrorÍndice fuera de rango[1,2,3][10]
KeyErrorClave no existe en dictd["x"]
FileNotFoundErrorArchivo no encontradoopen("x.txt")
AttributeErrorAtributo inexistenteNone.upper()
NameErrorVariable no definidaprint(x)

Capturar múltiples excepciones

def dividir(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        print("Error: no se puede dividir por cero")
    except TypeError:
        print("Error: los argumentos deben ser números")
    return None

# También podés capturar varias en una sola línea
try:
    resultado = int(input_dato) / divisor
except (ValueError, ZeroDivisionError) as e:
    print(f"Error: {e}")

Obtener información del error

try:
    numero = int("abc")
except ValueError as e:
    print(f"Tipo de error : {type(e).__name__}")
    print(f"Mensaje       : {e}")

# Capturar cualquier excepción (usar con cuidado)
try:
    resultado = 10 / 0
except Exception as e:
    print(f"Ocurrió un error: {e}")
Evitá capturar todo con Exception o bare except

Usar except: sin especificar el tipo atrapa incluso errores del sistema como KeyboardInterrupt. Siempre que puedas, especificá el tipo de excepción que esperás.

Lanzar excepciones con raise

Podés lanzar tus propias excepciones para validar datos en funciones:

def calcular_descuento(precio, porcentaje):
    if precio < 0:
        raise ValueError("El precio no puede ser negativo")
    if not 0 <= porcentaje <= 100:
        raise ValueError("El porcentaje debe estar entre 0 y 100")
    return precio * (1 - porcentaje / 100)

try:
    print(calcular_descuento(100, 20))   # 80.0
    print(calcular_descuento(-50, 10))   # ValueError
except ValueError as e:
    print(f"Error de validación: {e}")

Ejemplo Completo

Conversor de datos con manejo robusto de errores:

def convertir_a_numero(texto):
    """Intenta convertir un string a int o float."""
    try:
        return int(texto)
    except ValueError:
        try:
            return float(texto)
        except ValueError:
            raise ValueError(f"'{texto}' no es un número válido")

def procesar_datos(datos):
    """Procesa una lista de strings y convierte los que pueda."""
    resultados = []
    errores    = []

    for item in datos:
        try:
            num = convertir_a_numero(item.strip())
            resultados.append(num)
        except ValueError as e:
            errores.append({"valor": item, "error": str(e)})

    return resultados, errores

# Datos con mezcla de válidos e inválidos
entradas = ["42", "3.14", "hola", "100", "", "7", "???"]

numeros, problemas = procesar_datos(entradas)

print(f"Convertidos ({len(numeros)}): {numeros}")
print(f"Suma de válidos : {sum(numeros):.2f}")

if problemas:
    print(f"\nErrores ({len(problemas)}):")
    for p in problemas:
        print(f"  '{p['valor']}' → {p['error']}")
Probá el Ejemplo 3: Conversor de datos

Buenas Prácticas

  • Específico antes que general — capturá ValueError antes que Exception
  • No silencies errores — un except: pass vacío oculta problemas reales
  • Usá finally para liberar recursos — cerrar archivos, conexiones, etc.
  • raise para validar entradas — mejor fallar temprano con un mensaje claro
  • Logueá los errores — en producción, registrá los errores en vez de solo imprimirlos
  • Mensajes descriptivos — "El precio no puede ser negativo" es mejor que "Error"