Saltar al contenido
src / articulos / 08-manejo-de-excepciones.md

Manejo de Excepciones en Python

Emilio Castro //

La regla de oro en ingeniería de confiabilidad es asumir que todos los componentes van a fallar eventualmente. Los discos se llenan, las APIs exceden sus límites de cuota, las configuraciones traen formatos corruptos y los tokens de acceso caducan.

Un script de Python que asume que el “camino feliz” siempre se ejecutará, es un script que terminará colapsando tu automatización nocturna. Para construir herramientas resilientes (tolerantes a fallos), utilizamos el manejo de excepciones.

Control Básico: try y except

Las sentencias try y except actúan como un escudo protector alrededor de código propenso a fallar (operaciones de red, E/S de discos, parseos). Si la operación genera una excepción, en lugar de interrumpir el flujo del programa, el intérprete transfiere el control al bloque except.

# Simulamos la lectura de una configuración crítica de despliegue
try:
    with open('/etc/app/config.json', 'r') as file:
        config = file.read()
        print("Configuración cargada correctamente.")
except FileNotFoundError:
    # Capturamos el error específico sin abortar el script
    print("[ERROR] Archivo config.json no encontrado. Inicializando con valores por defecto.")
    config = "{}" # Valor de respaldo

Filtrado de Excepciones Específicas

En la infraestructura rara vez ocurre solo un tipo de error. Por ejemplo, al hacer una solicitud HTTP a una API interna, la petición podría fallar por múltiples motivos: el servidor no existe (DNS), la conexión expiró (Timeout) o la respuesta no es un JSON válido (ValueError).

import json

# Manejo multi-excepción para la evaluación de una carga JSON simulada
payload_recibido = "{ nombre: servidor-1 " # JSON malformado (falta comilla y cierre)

try:
    # Intentamos parsear la cadena
    datos = json.loads(payload_recibido)
except TypeError:
    print("[ALERTA] Se recibió un tipo de dato inválido en lugar de una cadena.")
except json.JSONDecodeError as error:
    # Asignamos el error a la variable 'error' para analizar la traza
    print(f"[CRÍTICO] Falló el parseo de la configuración: {error}")
    # Salida esperada: Falló el parseo... Expecting property name enclosed in double quotes...

Flujos de Limpieza: else y finally

El bloque else se ejecuta solo si el bloque try finalizó exitosamente sin levantar excepciones.

Por otro lado, el bloque finally se ejecutará siempre, sin importar si ocurrió un fallo o un éxito. Es la estructura ideal para la liberación de recursos operativos críticos: cerrar puertos TCP abiertos, sesiones de base de datos o manejadores de archivos.

# Intento de conexión a un socket
try:
    print("Estableciendo túnel SSH hacia la instancia bastion...")
    # Simulamos un fallo (ej. llave privada denegada)
    conexion = 10 / 0
except ZeroDivisionError:
    print("[ERROR] Fallo de autenticación. Conexión rechazada.")
else:
    print("Túnel establecido exitosamente. Ejecutando comandos...")
finally:
    print("[LIMPIEZA] Liberando socket local TCP y terminando sesión SSH.")

Disparar Excepciones Manuales (raise)

Como desarrolladores de automatizaciones, a veces necesitamos generar nuestros propios errores. Si un script recibe variables de entorno con formatos inseguros, no debemos continuar procesándolas; debemos abortar la ejecución intencionalmente mediante raise.

def validar_version_motor(version):
    """Comprueba que el motor cumpla los requisitos corporativos antes de desplegar."""
    if float(version) < 14.0:
        # Forzamos una excepción (Value Error) interrumpiendo el flujo
        raise ValueError(f"Versión de motor no soportada ({version}). Mínima requerida: 14.0.")
    return True

try:
    # Intentamos desplegar una base de datos legada
    validar_version_motor("12.5")
except ValueError as e:
    print(f"[RECHAZO PIPELINE CI/CD] {e}")

Manejar excepciones es transformar la debilidad y el caos inherente de los sistemas en previsibilidad operativa. Los scripts que atrapan y reportan sus errores claramente aceleran la depuración cuando te llaman a las 3:00 AM para diagnosticar un incidente.