Bucles en Python
La automatización existe porque los humanos somos pésimos repitiendo tareas con exactitud. Si necesitas reiniciar un servicio en un servidor, escribes un comando. Si necesitas hacerlo en 500 servidores, escribes un bucle. No hay romanticismo en eso: es mecánica pura.
Python tiene dos estructuras iterativas principales: for y while. La elección entre una y otra no es trivial. Un script que usa while donde debería usar for no sólo es más largo, es una señal de que quien lo escribió no entendió el problema.
Bucle for (Iteración Definida)
Usamos for cuando ya tenemos la colección: una lista de IPs, los puertos de un firewall, las claves de un diccionario de configuración. El bucle recorre cada elemento en orden, sin más.
# Iterar sobre una lista de nodos de un clúster
nodos_db = ["db-master-01", "db-replica-01", "db-replica-02"]
for nodo in nodos_db:
print(f"Ejecutando backup en: {nodo}...")
A veces no tenemos una colección, sólo un número: reintentar una conexión 3 veces, esperar N segundos, ejecutar un chequeo cada cierto intervalo. Para eso existe range(), que genera la secuencia al vuelo sin que tengas que construirla a mano.
# Configurar 3 reintentos para una conexión de red
max_retries = 3
for intento in range(max_retries):
print(f"Intento de conexión {intento + 1}/{max_retries}")
# Lógica de conexión aquí...
Bucle while (Iteración Indefinida)
El while no itera sobre una colección. Se repite mientras una condición sea True, lo que lo convierte en la herramienta correcta para polling: consultar el estado de un servicio hasta que responda, sin saber de antemano cuántas veces vas a necesitar preguntar. Esa incertidumbre es exactamente lo que lo define. Si ya sabes cuántas iteraciones necesitas, usa for y no lo pienses más.
# Simulación de un polling para esperar a que un servicio levante
servicio_listo = False
intentos = 0
while not servicio_listo and intentos < 5:
print("El servicio aún no responde. Esperando 5 segundos...")
intentos += 1
# Aquí iría la lógica real de comprobación
if intentos == 3:
servicio_listo = True # Simulamos que levanta al 3er intento
print("Servicio en línea. Continuando despliegue.")
Control de Flujo: break y continue
No siempre queremos que el bucle termine de manera natural.
break corta la ejecución ahí mismo. Si encontraste el nodo que falló, revisar los 400 restantes es tiempo tirado a la basura. Sal del bucle y actúa.
servidores = ["web-1 (OK)", "web-2 (FAIL)", "web-3 (OK)", "web-4 (OK)"]
for server in servidores:
print(f"Analizando {server}")
if "FAIL" in server:
print(">>> Fallo crítico detectado. Abortando análisis.")
break # El bucle termina inmediatamente aquí
continue opera diferente: descarta la iteración actual y salta a la siguiente sin salir del bucle. Úsalo cuando un elemento no necesita procesamiento y forzar una condición negativa enredaría la lectura del bloque. Es una herramienta quirúrgica. No abuses.
puertos = [80, 443, 22, 8080]
for puerto in puertos:
if puerto == 22:
print(f"Ignorando puerto {puerto} (Administrativo)")
continue # Salta el resto del bloque y evalúa el siguiente puerto
print(f"Configurando reglas de firewall para el puerto de aplicación {puerto}")