Workflow Automation

Windmill pour l'ingénierie des données : Créer des scripts ETL reproductibles avec Python et SQL

L'ingénierie des données moderne ne se limite plus au simple transfert de données d'un point A à un point B ; il s'agit de construire des systèmes résilients, observables et reproductibles. À mesure que les piles de données gagnent en complexité, le besoin d'outils comblant le fossé entre le scriptage agile et la gestion robuste des flux de travail devient critique. Windmill s'est imposé comme une solution puissante pour ce problème précis, offrant une plateforme auto-hébergeable qui permet aux développeurs de construire, déployer et planifier des flux de travail complexes en utilisant des langages familiers comme Python et SQL. Dans ce guide, nous explorerons comment exploiter Windmill pour créer des scripts ETL non seulement efficaces, mais également entièrement reproductibles et maintenables.

Pourquoi choisir Windmill pour les pipelines ETL ?

Les outils ETL traditionnels souffrent souvent de deux inconvénients majeurs : une courbe d'apprentissage abrupte impliquant des interfaces graphiques propriétaires, ou la fragilité des scripts autonomes qui manquent de contrôle de version et de surveillance. Windmill résout les deux en traitant les flux de travail comme du code. Il fournit une interface low-code/no-code pour l'orchestration tout en permettant une personnalisation approfondie via des étapes de code. Cette approche hybride garantit que les ingénieurs des données peuvent prototyper rapidement avec SQL et Python, tandis que les équipes DevOps peuvent gérer les déploiements via Git.

Les principaux avantages incluent :

  • Approche centrée sur le code : Chaque étape est un script ou un appel API, facilitant l'intégration avec les pipelines CI/CD existants.
  • Prise en charge native de Python et SQL : Accès direct à vos entrepôts de données sans dépendances lourdes aux SDK.
  • Reproductibilité : Les paramètres d'entrée exacts et les versions de code sont journalisés pour chaque exécution, garantissant que vous pouvez déboguer les problèmes passés.
  • Sécurité auto-hébergée : Conservez vos données et votre code dans les limites de votre infrastructure.

Concevoir un flux de travail ETL reproductible

Un flux de travail ETL reproductible dans Windmill se compose généralement de trois étapes principales : Extraction, Transformation et Chargement. L'élément critique pour la reproductibilité est la validation des entrées et la gestion de la configuration. En définissant des entrées typées dans Windmill, vous vous assurez que chaque exécution du pipeline sait exactement quels paramètres utiliser, éliminant ainsi les scénarios du type « ça marche sur ma machine ».

Étape 1 : Extraction de données avec SQL

Windmill vous permet de vous connecter directement à votre base de données (PostgreSQL, MySQL, etc.) et d'exécuter des requêtes SQL en tant qu'étapes de flux de travail. C'est idéal pour la phase d'Extraction. Considérons une requête simple pour récupérer les données brutes des commandes.


# Étape Windmill : Requête SQL
# Connexion à votre instance PostgreSQL

def extract_raw_orders(conn, start_date: str, end_date: str):
    query = f"""
        SELECT 
            order_id, 
            customer_id, 
            amount, 
            created_at 
        FROM 
            public.orders 
        WHERE 
            created_at BETWEEN '{start_date}' AND '{end_date}'
    """
    return conn.execute(query).fetchall()

Étape 2 : Transformation avec Python

Une fois les données extraites, les étapes Python brillent lors de la phase de Transformation. L'environnement d'exécution Python de Windmill prend en charge les bibliothèques standard et même pandas pour des manipulations plus complexes. Pour assurer la reproductibilité, évitez de coder la logique en dur ; passez plutôt des objets de configuration ou utilisez des bibliothèques versionnées.


# Étape Windmill : Transformation Python

import pandas as pd
from datetime import datetime

def transform_orders(raw_data: list[dict]):
    df = pd.DataFrame(raw_data)
    
    # Calculer les métriques dérivées
    df['order_year'] = df['created_at'].dt.year
    df['is_high_value'] = df['amount'] > 100
    
    # Nettoyer les données : Supprimer les valeurs nulles dans les champs critiques
    df = df.dropna(subset=['order_id', 'customer_id'])
    
    return df.to_dict('records')

Étape 3 : Chargement avec des scripts versionnés

Pour la phase de Chargement, les meilleures pratiques dictent l'utilisation d'opérations idempotentes. Dans Windmill, vous pouvez écrire une étape Python qui insère ou met à jour (upsert) les données dans votre entrepôt de données (comme Snowflake ou BigQuery). L'utilisation d'un upsert garantit que la réexécution du pipeline pour la même plage de dates ne crée pas de doublons, un aspect clé de la reproductibilité.


# Étape Windmill : Chargement Python (Upsert Idempotent)

import sqlalchemy

def load_orders(transformed_data: list[dict], warehouse_conn):
    engine = sqlalchemy.create_engine(warehouse_conn.url)
    for record in transformed_data:
        stmt = sqlalchemy.dialects.postgresql.upsert('analytics.orders', record)
        with engine.begin() as conn:
            conn.execute(stmt)

Meilleures pratiques pour la reproductibilité

  1. Contrôle de version des entrées : Utilisez les schémas d'entrée de Windmill pour définir les paramètres requis. Journalisez ces entrées avec les métadonnées d'exécution du flux de travail.
  2. Épingler les dépendances : Dans les étapes Python, utilisez le fichier `requirements.txt` géré par Windmill pour vous assurer que les mêmes versions de bibliothèques sont utilisées dans tous les environnements.
  3. Modèles de données immuables : Dans la mesure du possible, utilisez des tables partitionnées ou des stratégies de capture instantanée (snapshot) dans votre base de données de destination pour préserver les états historiques des données.
  4. Tester localement d'abord : Windmill prend en charge l'exécution locale des étapes. Testez toujours les transformations Python sur des données d'échantillon avant de déployer le flux de travail complet.

Conclusion

La construction de pipelines ETL avec Windmill fait évoluer le paradigme des scripts fragiles vers des flux de travail gérés et reproductibles. En combinant la flexibilité de Python et l'efficacité de SQL au sein d'une plateforme unifiée, les ingénieurs des données peuvent construire des systèmes plus faciles à déboguer, à mettre à l'échelle et à maintenir. L'accent mis sur les entrées typées et le code versionné garantit que chaque point de données dans votre entrepôt peut être retracé jusqu'à sa source exacte et sa logique de transformation. À mesure que votre pile de données grandit, l'adoption d'une approche centrée sur le code et les flux de travail comme Windmill portera ses fruits en termes de fiabilité et de vélocité de développement.

Share: