Introducción al Manejo de Errores en Python
El manejo robusto de errores es esencial para desarrollar aplicaciones confiables. En este tutorial cubriremos:
- Filosofías EAFP vs LBYL
- Jerarquía de excepciones
- Creación de excepciones personalizadas
- Uso estratégico de logging
- Herramientas avanzadas de debugging
1. Filosofías de Manejo de Errores
EAFP (Easier to Ask for Forgiveness than Permission)
try:
with open('archivo.txt') as f:
contenido = f.read()
except FileNotFoundError:
print("El archivo no existe")
LBYL (Look Before You Leap)
import os
if os.path.exists('archivo.txt'):
with open('archivo.txt') as f:
contenido = f.read()
else:
print("El archivo no existe")
Cuándo usar cada enfoque:
- EAFP: Ideal para Python (idiomático)
- LBYL: Útil cuando las verificaciones son económicas
2. Jerarquía de Excepciones
Principales excepciones built-in:
BaseException
├── SystemExit
├── KeyboardInterrupt
├── Exception
├── ArithmeticError
├── LookupError
├── OSError
└── RuntimeError
3. Excepciones Personalizadas
class ErrorDeValidacion(Exception):
"""Error cuando falla la validación de datos"""
def __init__(self, mensaje, codigo_error):
super().__init__(mensaje)
self.codigo_error = codigo_error
def validar_edad(edad):
if edad < 0:
raise ErrorDeValidacion("La edad no puede ser negativa", 1001)
4. Bloques Try/Except Avanzados
try:
resultado = 10 / divisor
except ZeroDivisionError:
print("Error: División por cero")
except TypeError:
print("Error: Tipo de dato incorrecto")
else:
print(f"Resultado: {resultado}")
finally:
print("Ejecución finalizada")
5. Context Managers para Manejo de Recursos
Implementación personalizada:
class GestorDB:
def __enter__(self):
self.conexion = crear_conexion_db()
return self.conexion
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"Error: {exc_val}")
self.conexion.close()
6. Configuración Profesional de Logging
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Configuración de handlers
console_handler = logging.StreamHandler()
file_handler = RotatingFileHandler('app.log', maxBytes=1e6, backupCount=3)
# Formato
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Añadir handlers
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# Ejemplo de uso
logger.info("Iniciando aplicación")
try:
1 / 0
except Exception:
logger.exception("Error crítico")
7. Herramientas de Debugging
PDB (Python Debugger)
import pdb
def funcion_problematica():
pdb.set_trace() # Punto de interrupción
# Código a depurar
cProfile para Análisis de Rendimiento
python -m cProfile mi_script.py
8. Ejemplos Prácticos
Cliente HTTP con Reintentos
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retries = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
session.mount('https://', HTTPAdapter(max_retries=retries))
Validación de Datos con Excepciones
def procesar_datos(datos):
if not isinstance(datos, dict):
raise TypeError("Se esperaba un diccionario")
if 'clave' not in datos:
raise ValueError("Falta clave obligatoria")
# Procesamiento...
9. Anti-patrones Comunes
❌ Captura demasiado amplia:
try:
# código
except: # ¡Evitar!
pass
✅ Mejor práctica:
try:
# código
except ValueError as e:
logger.error(f"Error de valor: {e}")
10. Buenas Prácticas
- Específica en las excepciones: Captura solo los errores que esperas
- Registra adecuadamente: Proporciona contexto en los logs
- Prueba los casos de error: Implementa unit tests para flujos de error
- Documenta los errores: Comenta qué excepciones puede lanzar cada función
Conclusión
El manejo profesional de errores implica:
- Uso adecuado de excepciones
- Logging estratégico
- Técnicas efectivas de debugging
- Implementación de patrones robustos
Recursos adicionales:
¡Ahora estás listo para manejar errores como un profesional en Python! 🚀
Deja una respuesta