1. Logging
Hoy nos sumergiremos en un tema que tal vez te salve un montón de neuronas y tiempo valioso: logging y manejo de errores. Incluso el programador más experimentado no está exento de errores, y tu tarea es hacer que esos errores sean predecibles y manejables. Imagina que eres un arqueólogo en una excavación, y tu objetivo es proteger tu expedición de derrumbes inesperados y trampas traicioneras; ¡el logging y el manejo de errores son tu brújula y escudo en esta misión de alto riesgo!
Cuando hablamos de logging en programación, nos referimos al proceso de registrar información sobre el funcionamiento del programa. Son procesos que ocurren dentro de tu código y que pueden no ser visibles a simple vista. Al registrar logs, dejas pistas como Hansel y Gretel dejaron migas de pan en el bosque para encontrar el camino de regreso a casa.
Configuración inicial de logging
Comencemos con las herramientas básicas en Python. Para logging, utilizaremos el módulo incorporado logging. Este es tu navaja suiza para registrar información sobre el flujo de tu programa.
import logging
# Configuración de logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Ejemplo de uso
logging.info("Inicio del script")
logging.error("Este es un error")
¿Qué niveles de logging existen?
- DEBUG: el nivel más detallado, usualmente útil solo para diagnosticar problemas.
- INFO: confirma que los procesos están funcionando como se espera.
- WARNING: señala algo inesperado y potencialmente problemático, pero el programa aún funciona.
- ERROR: solo errores graves que interrumpieron la ejecución de una función.
Puedes ajustar el nivel de logging para filtrar la información. Por ejemplo, si solo te interesan los errores y advertencias, configura el nivel logging.WARNING.
Ejemplo de logging en Selenium
Veamos cómo se puede aplicar logging en un proyecto con Selenium:
from selenium import webdriver
# Configuración de logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
try:
logging.info("Inicializando el controlador de Chrome")
driver = webdriver.Chrome()
logging.info("Abriendo la página Python.org")
driver.get("https://www.python.org")
logging.info("Finalización exitosa del trabajo")
except Exception as e:
logging.error(f"Ocurrió un error: {e}")
finally:
driver.quit()
Este ejemplo demuestra cómo integrar logging en tu script Selenium para monitorear su rendimiento. Usamos try, except y finally para manejar errores, hablaremos de esto en detalle más adelante.
2. Manejo de errores en Selenium
En programación, como en la vida, los errores son inevitables. Sin embargo, podemos controlar cómo reaccionamos ante ellos. Usar try, except, else y finally permite capturar y manejar errores de manera elegante.
Recordando el manejo de excepciones
Repasemos cómo funciona el manejo de excepciones:
try:
# Código que podría generar una excepción
result = 10 / 0
except ZeroDivisionError as e:
# Código que se ejecutará si ocurre una excepción ZeroDivisionError
logging.error("¡División por cero no permitida!")
else:
# Código que se ejecutará si no ocurre ninguna excepción
logging.info("Operación completada exitosamente")
finally:
# Código que se ejecutará de todas maneras
logging.info("Operaciones finalizadas")
Tu código en el bloque try se ejecutará. Si ocurre un error del tipo ZeroDivisionError, el código dentro del bloque except se ejecutará y el programa no se detendrá. El bloque else se usa para ejecutar código si no se generó ninguna excepción. Finalmente, el bloque finally siempre se ejecuta, independientemente de si hubo un error o no.
Manejo de errores en Selenium
Selenium ofrece una serie de excepciones integradas para manejar diferentes situaciones. Aquí hay algunas excepciones útiles y cómo usarlas.
-
NoSuchElementException: ocurre si no se encuentra un elemento. Úsala para verificar la disponibilidad de elementos.Pythontry: element = driver.find_element(By.ID, "element_id") except NoSuchElementException: logging.warning("El elemento con ID 'element_id' no fue encontrado.") -
TimeoutException: ocurre si un elemento esperado no aparece en la página dentro del tiempo establecido. Úsala para gestionar tiempos de espera.Pythonfrom selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "element_id")) ) except TimeoutException: logging.error("El tiempo de espera para el elemento con ID 'element_id' expiró.") -
ElementClickInterceptedException: ocurre si un elemento está bloqueado por otro elemento y no se puede hacer clic. Útil en casos donde ventanas emergentes bloquean elementos.Pythonfrom selenium.common.exceptions import ElementClickInterceptedException try: driver.find_element(By.ID, "button_id").click() except ElementClickInterceptedException: logging.warning("El elemento está bloqueado por otro elemento y no se puede hacer clic.")
Reintentos y lógica de recuperación
Para hacer tu script más resistente, puedes implementar un mecanismo de reintentos en caso de errores. Por ejemplo, si un sitio web está temporalmente inactivo o no se encuentra un elemento, el script puede intentar realizar la acción varias veces antes de finalizar con un error.
import time
def retry_find_element(driver, by, value, retries=3):
attempt = 0
while attempt < retries:
try:
element = driver.find_element(by, value)
logging.info(f"Elemento encontrado: {value}")
return element
except NoSuchElementException:
attempt += 1
logging.warning(f"Intento {attempt} fallido, reintento en 2 segundos...")
time.sleep(2)
logging.error(f"Elemento no encontrado después de {retries} intentos.")
return None
Consejos para scripts robustos y confiables
- Usa esperar explícitas: Configura esperas explícitas para elementos que no aparecen de inmediato. Esto reducirá la cantidad de errores por retrasos en la carga.
- Implementa bloques try-except en cada etapa: Esto permitirá registrar errores y evitar que el script se detenga debido a fallas menores.
- Realiza reintentos para pasos críticos: Si el error puede ser temporal, configura reintentos con un intervalo de unos segundos.
- Registra cada paso: Registrar cada etapa clave ayuda a analizar el progreso del script y detectar errores ocultos.
- Configura notificaciones para errores críticos: Por ejemplo, se puede enviar un correo o mensaje a un chat si un error de nivel CRITICAL se registra en los logs.
3. Sacando provecho de los logs
Ahora que hemos aprendido a registrar y manejar errores, demos un paso más y veamos cómo sacarle el máximo provecho a los logs.
Elegir el lugar y el formato de los logs
Usa un archivo para almacenar tus logs si quieres conservarlos para análisis. Esto es como llevar un diario que puedes releer y analizar para evitar errores futuros. Configuremos logging para registrar en un archivo:
logging.basicConfig(filename='app.log', filemode='w', level=logging.INFO)
# Ahora todos los logs se guardarán en app.log
logging.info("El registro de logs en archivo ha comenzado.")
Análisis de logs
Analiza tus logs para identificar errores comunes o problemas de rendimiento. Tal vez tu script enfrenta problemas solo en ciertos días u horarios, y esto solo se puede notar al estudiar los logs en profundidad. Este análisis es tu proceso personal de detective, que ayuda a comprender mejor cómo funciona tu aplicación.
GO TO FULL VERSION