Gestion des erreurs réseau
Un appel HTTP peut échouer pour de nombreuses raisons : API éteinte, réseau coupé, timeout, paramètres invalides... Le dashboard doit gérer tous ces cas sans crasher.
Deux catégories d'erreurs
Les erreurs HTTP se divisent en deux catégories :
| Catégorie | Cause | Conséquence en Python |
|---|---|---|
| Erreurs réseau | L'appel HTTP échoue complètement | Exception Python levée par requests |
| Erreurs HTTP | L'appel atteint le serveur mais il retourne un code d'erreur | Pas d'exception — il faut vérifier status_code |
Distinction cruciale
requests.get() ne lève jamais d'exception pour un code HTTP 400 ou 500. L'appel a techniquement réussi (le serveur a répondu). Seules les erreurs réseau (API inaccessible, timeout) lèvent des exceptions.
Erreurs réseau : les exceptions requests
Les principales exceptions levées par requests quand l'appel échoue :
| Situation | Exception | Exemple |
|---|---|---|
| API éteinte / inaccessible | ConnectionError | Le serveur Flask n'est pas lancé |
| Délai dépassé | Timeout | Le serveur ne répond pas dans le délai imparti |
| Mauvais paramètre côté serveur | Code 400 (pas d'exception) | Paramètre invalide envoyé à l'API |
| Ressource inexistante | Code 404 (pas d'exception) | Endpoint ou donnée non trouvé |
| Erreur interne du serveur | Code 500 (pas d'exception) | Bug dans le code Flask |
Gérer les exceptions réseau
import requests
import streamlit as st
url = "http://localhost:5000/api/v1/ventes/par-region"
try:
response = requests.get(url, timeout=5) # TOUJOURS spécifier un timeout
except requests.exceptions.ConnectionError:
st.error("Impossible de joindre l'API. Vérifiez que le serveur Flask est lancé.")
st.stop()
except requests.exceptions.Timeout:
st.error("L'API ne répond pas dans les délais. Réessayez plus tard.")
st.stop()
except requests.exceptions.RequestException as e:
st.error(f"Erreur réseau inattendue : {e}")
st.stop()
Toujours spécifier un timeout
Sans timeout, requests.get() attend indéfiniment si le serveur ne répond pas. Votre dashboard Streamlit serait alors figé sans aucun message d'erreur. Spécifiez toujours un timeout en secondes.
st.stop() : arrêter l'exécution
st.stop() arrête l'exécution du script Streamlit à cet endroit. C'est l'équivalent d'un return dans une fonction : tout le code après st.stop() n'est pas exécuté.
Inutile de continuer à afficher des graphiques si les données n'ont pas pu être récupérées.
Que se passe-t-il si vous n'ajoutez pas de timeout à requests.get() et que le serveur ne répond pas ?
Erreurs HTTP : vérifier le code de retour
Quand l'appel HTTP atteint le serveur mais que celui-ci retourne une erreur (400, 404, 500...), requests ne lève pas d'exception. Il faut vérifier manuellement.
Option 1 : vérification manuelle avec response.ok
response = requests.get(url, timeout=5)
if not response.ok:
st.error(f"Erreur API (code {response.status_code})")
st.stop()
data = response.json()
Option 2 : raise_for_status()
La méthode raise_for_status() lève une exception HTTPError si le code de retour est supérieur ou égal à 400 :
try:
response = requests.get(url, timeout=5)
response.raise_for_status() # Lève HTTPError si code >= 400
except requests.exceptions.HTTPError as e:
if response.status_code == 404:
st.warning("Aucune donnée trouvée pour ces critères.")
elif response.status_code == 400:
st.error("Paramètres invalides. Vérifiez vos filtres.")
elif response.status_code >= 500:
st.error("Erreur serveur. Contactez l'administrateur.")
st.stop()
raise_for_status() est recommandé
raise_for_status() permet de traiter les erreurs réseau et HTTP dans le même bloc try/except. Le code est plus lisible.
Que fait response.raise_for_status() si le code HTTP est 200 ?
Pattern complet : la fonction api_get
Plutôt que de répéter la gestion d'erreurs à chaque appel, centralisez-la dans une fonction :
import requests
import streamlit as st
def api_get(endpoint: str, params: dict = None) -> dict | None:
"""Appelle un endpoint GET de l'API et retourne le JSON, ou None en cas d'erreur."""
base_url = "http://localhost:5000/api/v1"
try:
response = requests.get(f"{base_url}/{endpoint}", params=params, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.ConnectionError:
st.error("API inaccessible. Vérifiez que le serveur Flask est lancé.")
return None
except requests.exceptions.Timeout:
st.error("L'API ne répond pas dans les délais.")
return None
except requests.exceptions.HTTPError:
code = response.status_code
if code == 404:
st.warning("Aucune donnée trouvée pour ces critères.")
else:
st.error(f"Erreur API (code {code}).")
return None
except Exception as e:
st.error(f"Erreur inattendue : {e}")
return None
Utilisation dans Streamlit
import pandas as pd
import plotly.express as px
# Appel simple et propre
data = api_get("ventes/par-region", params={"annee": annee})
if data is not None:
df = pd.DataFrame(data["data"])
fig = px.bar(df, x="region", y="chiffre_affaires")
st.plotly_chart(fig, use_container_width=True)
Le code métier (graphiques, affichage) est séparé de la gestion d'erreurs. Si api_get retourne None, on ne fait rien — l'erreur a déjà été affichée.
st.spinner : feedback visuel pendant le chargement
Un appel HTTP prend du temps (même en local). Utilisez st.spinner pour informer l'utilisateur :
with st.spinner("Chargement des données..."):
data = api_get("ventes/par-region", params={"annee": annee})
if data is not None:
df = pd.DataFrame(data["data"])
st.dataframe(df)
st.spinner affiche un indicateur de chargement pendant que le code dans le bloc with s'exécute. Sans lui, l'utilisateur ne sait pas si le dashboard charge ou s'il est figé.
Pourquoi la fonction api_get retourne-t-elle None plutôt que de lever une exception ?
À retenir
Points clés
- Deux catégories d'erreurs : réseau (exceptions Python) et HTTP (codes de retour)
requests.get()ne lève jamais d'exception pour un code 400 ou 500- Toujours spécifier
timeoutpour éviter les blocages infinis raise_for_status()convertit les erreurs HTTP en exceptionsst.stop()arrête l'exécution du script Streamlit- Pattern
api_get: centralise la gestion d'erreurs, retourneNoneen cas de problème st.spinner: feedback visuel pendant les appels réseau
Votre dashboard gère maintenant les erreurs réseau. Mais un autre problème peut survenir dans certains contextes : le CORS.