🎯 Objectif : À la fin de ce chapitre, tu maîtriseras les conditions, boucles, fonctions et compréhensions de listes — les outils pour écrire de vrais scripts d’automatisation. ⏱️ Durée estimée : 45 minutes | Niveau : Débutant-Intermédiaire
Conditions : if, elif, else
Les conditions contrôlent le flux d’exécution. En Python, l’indentation (4 espaces) délimite les blocs — pas d’accolades.
status_code = 503
if status_code == 200:
print("OK")
elif status_code == 404:
print("Not Found")
elif status_code >= 500:
print("Server Error — alerte critique !")
else:
print(f"Code inattendu : {status_code}")
Combiner des conditions
cpu = 85
memory = 92
if cpu > 80 and memory > 90:
print("ALERTE : charge critique sur CPU et mémoire")
elif cpu > 80 or memory > 90:
print("WARNING : une ressource sous pression")
# Vérification de plage (syntaxe Python élégante)
port = 8080
if 1024 <= port <= 65535:
print("Port valide (non privilégié)")
Opérateur ternaire
Une condition sur une seule ligne, utile pour les assignations simples.
env = "production"
debug = True if env == "development" else False
status = "healthy" if cpu < 80 else "degraded"
💡 L’opérateur ternaire Python se lit comme du français : “debug est True si env est development, sinon False”.
Boucles : for et while
La boucle for
La boucle for parcourt n’importe quelle séquence : liste, string, range, dict…
# Parcourir une liste
servers = ["web-01", "web-02", "db-01"]
for server in servers:
print(f"Vérification de {server}...")
# Avec range (début, fin, pas)
for i in range(5): # 0, 1, 2, 3, 4
print(f"Tentative {i + 1}")
for i in range(0, 100, 10): # 0, 10, 20, ..., 90
print(i)
enumerate et zip
Deux outils indispensables pour les boucles Python.
# enumerate : accéder à l'index ET la valeur
services = ["nginx", "postgresql", "redis"]
for index, service in enumerate(services):
print(f"{index + 1}. {service}")
# zip : parcourir plusieurs listes en parallèle
servers = ["web-01", "web-02", "web-03"]
ips = ["10.0.1.1", "10.0.1.2", "10.0.1.3"]
for server, ip in zip(servers, ips):
print(f"{server} → {ip}")
La boucle while
while s’exécute tant que la condition est vraie. Attention aux boucles infinies.
retries = 0
max_retries = 5
connected = False
while not connected and retries < max_retries:
print(f"Tentative {retries + 1}...")
if retries == 2: # Simulation : succès à la 3e tentative
connected = True
print("Connecté !")
retries += 1
if not connected:
print("Échec après 5 tentatives")
break et continue
# break : sortir immédiatement de la boucle
for port in range(8000, 9000):
if port == 8080:
print(f"Port {port} trouvé !")
break
# continue : passer à l'itération suivante
logs = ["INFO: started", "ERROR: disk full", "INFO: request", "WARNING: high CPU"]
for log in logs:
if log.startswith("INFO"):
continue # On ignore les logs INFO
print(f"⚠️ {log}")
🔥 break est particulièrement utile dans les boucles while True pour les retry patterns — tu boucles indéfiniment et tu sors quand la condition de succès est remplie.
Fonctions : organiser et réutiliser
Définir une fonction
def check_disk_usage(path, threshold=80):
"""Vérifie l'utilisation disque et retourne un statut."""
usage = 75 # Simulation
if usage > threshold:
return "CRITICAL", usage
return "OK", usage
# Appels
status, usage = check_disk_usage("/var/log")
status, usage = check_disk_usage("/data", threshold=90)
💡 La triple-quote sous def est une docstring. Elle documente ce que fait la fonction. C’est une convention Python, pas juste un commentaire.
Types d’arguments
# Positionnels et nommés avec valeurs par défaut
def deploy(service, env="staging", replicas=1):
print(f"Déploiement de {service} en {env} ({replicas} réplicas)")
deploy("nginx") # staging, 1 réplica
deploy("nginx", "production", 3) # production, 3 réplicas
deploy("nginx", replicas=5, env="prod") # nommés dans n'importe quel ordre
# *args : nombre variable d'arguments positionnels
def log_event(*messages, level="INFO"):
for msg in messages:
print(f"[{level}] {msg}")
log_event("Démarrage", "Config chargée")
log_event("Erreur fatale", level="ERROR")
# **kwargs : nombre variable d'arguments nommés
def create_resource(**config):
for key, value in config.items():
print(f" {key}: {value}")
create_resource(name="web-server", cpu=2, memory="4Gi")
Fonctions lambda
Une fonction anonyme sur une seule ligne. Utile pour les tris et les callbacks.
# Tri personnalisé par CPU usage
servers = [
{"name": "web-01", "cpu": 85},
{"name": "web-02", "cpu": 42},
{"name": "web-03", "cpu": 67},
]
servers.sort(key=lambda s: s["cpu"])
# Résultat : web-02 (42), web-03 (67), web-01 (85)
# Filtre avec filter()
critical = list(filter(lambda s: s["cpu"] > 80, servers))
⚠️ Les lambdas sont limitées à une seule expression. Pour toute logique complexe, utilise une fonction def classique.
Compréhensions de listes
Les compréhensions sont la façon Python de transformer et filtrer des collections en une seule ligne. C’est puissant, concis et lisible.
Syntaxe de base
# Boucle classique
squares = []
for i in range(10):
squares.append(i ** 2)
# Compréhension (équivalent en 1 ligne)
squares = [i ** 2 for i in range(10)]
Avec filtre
# Filtrer les ports non-privilégiés
ports = [22, 80, 443, 3000, 5432, 8080]
high_ports = [p for p in ports if p > 1024]
# [3000, 5432, 8080]
Exemples DevOps concrets
# Générer des noms de serveurs
servers = [f"web-{i:02d}" for i in range(1, 11)]
# ['web-01', 'web-02', ..., 'web-10']
# Extraire les IPs d'une liste de dicts
nodes = [
{"name": "node-1", "ip": "10.0.1.1"},
{"name": "node-2", "ip": "10.0.1.2"},
]
ips = [node["ip"] for node in nodes]
# Filtrer les serveurs en erreur depuis un dict de statuts
statuses = {"web-01": "ok", "web-02": "error", "db-01": "ok"}
errors = [name for name, status in statuses.items() if status == "error"]
# ['web-02']
# Parser des variables d'environnement
env_vars = ["DB_HOST=localhost", "DB_PORT=5432", "DB_NAME=app"]
config = {k: v for k, v in (var.split("=") for var in env_vars)}
# {'DB_HOST': 'localhost', 'DB_PORT': '5432', 'DB_NAME': 'app'}
🎯 Règle : si ta compréhension dépasse une ligne ou devient illisible, reviens à une boucle for classique. La lisibilité prime sur la concision.
Gestion des erreurs : try/except
Les erreurs arrivent : fichier manquant, API timeout, format invalide. try/except permet de les gérer proprement sans crasher le programme.
def read_config(filepath):
"""Lit un fichier de configuration."""
try:
with open(filepath) as f:
return f.read()
except FileNotFoundError:
print(f"⚠️ Fichier {filepath} introuvable")
return None
except PermissionError:
print(f"⚠️ Pas les droits sur {filepath}")
return None
# Avec finally (s'exécute toujours, erreur ou pas)
def connect_db(host, port):
connection = None
try:
connection = create_connection(host, port)
return connection
except ConnectionError as e:
print(f"Échec de connexion : {e}")
return None
finally:
if connection and not connection.is_active:
connection.close()
💡 Toujours catcher des exceptions spécifiques (FileNotFoundError, ValueError). Un except Exception nu masque les vrais bugs.
Cas entreprise : moniteur de conteneurs
Contexte : tu écris un script qui analyse l’état de conteneurs Docker et génère un rapport.
containers = [
{"id": "a1b2c3", "name": "nginx", "status": "running", "cpu": 12.5},
{"id": "d4e5f6", "name": "postgres", "status": "running", "cpu": 45.2},
{"id": "g7h8i9", "name": "redis", "status": "exited", "cpu": 0.0},
{"id": "j0k1l2", "name": "worker", "status": "running", "cpu": 88.7},
{"id": "m3n4o5", "name": "api", "status": "running", "cpu": 67.3},
]
def container_report(containers):
"""Génère un rapport sur les conteneurs."""
running = [c for c in containers if c["status"] == "running"]
exited = [c for c in containers if c["status"] == "exited"]
print(f"📊 Rapport : {len(running)} actifs, {len(exited)} arrêtés\n")
# Conteneur le plus gourmand
if running:
top = max(running, key=lambda c: c["cpu"])
avg = sum(c["cpu"] for c in running) / len(running)
print(f"🔥 Plus gourmand : {top['name']} ({top['cpu']}%)")
print(f"📈 CPU moyen : {avg:.1f}%\n")
# Détail par conteneur
for c in containers:
icon = "🟢" if c["status"] == "running" else "🔴"
alert = " ⚠️ HIGH" if c["cpu"] > 80 else ""
print(f" {icon} {c['name']:10} CPU: {c['cpu']:5.1f}%{alert}")
container_report(containers)
Ce script combine tout : compréhensions, fonctions, conditions, f-strings, lambda dans max().
Les pièges classiques
⚠️ Arguments mutables par défaut — def add(item, lst=[]) partage la même liste entre les appels. Utilise lst=None puis lst = lst or [].
⚠️ Boucle infinie — Oublier d’incrémenter le compteur dans un while. Toujours vérifier que la condition de sortie est atteignable.
⚠️ Indentation mélangée — Tabs et espaces ensemble causent des IndentationError. Configure ton éditeur sur 4 espaces, point final.
⚠️ Scope des variables — Une variable définie dans une fonction n’existe pas en dehors. Si tu as besoin de la valeur, retourne-la.
⚠️ except nu — except: sans type d’exception catche tout, y compris KeyboardInterrupt et SystemExit. Toujours spécifier le type d’exception.
Résumé
Tu as maintenant les outils pour écrire de vrais scripts Python :
- Conditions →
if/elif/else, opérateur ternaire, conditions chaînées - Boucles →
foravecrange/enumerate/zip,while,break/continue - Fonctions →
def, arguments par défaut,*args/**kwargs, lambdas - Compréhensions →
[expr for x in iterable if condition]pour listes, dicts, sets - Erreurs →
try/except/finallyavec des exceptions spécifiques
🎯 La combinaison conditions + boucles + fonctions + compréhensions couvre 90% de ce que tu écriras en scripts DevOps. Le prochain chapitre aborde les classes, les modules et la gestion de fichiers pour passer au niveau supérieur.
➡️ La suite : Classes, modules et fichiers
Contenu réservé aux abonnés
Ce chapitre fait partie de la formation complète. Abonne-toi pour débloquer tous les contenus.
Débloquer pour 29 CHF/moisLe chapitre 1 de chaque formation est gratuit.
Série pas encore débloquée
Termine la série prérequise d'abord pour accéder à ce contenu.
Aller à la série prérequiseSérie : Python DevOps
2 / 8Sur cette page
Articles liés
Python : les bases du langage
Premiers pas en Python pour le DevOps : variables, types de données, opérateurs, strings, listes, dictionnaires, tuples et sets.
Gestion d'erreurs et fichiers
Try/except, manipulation de fichiers (JSON, YAML, CSV), environnements virtuels avec venv/pip, et pattern d'un script DevOps propre.
Python avancé : classes et modules
Programmation orientée objet en Python : classes, héritage, méthodes spéciales, et organisation du code avec les modules et packages.