Les formules Python
La formule Python vous permet d'écrire des traitements personnalisés qui dépassent les capacités des formules natives (arithmétique, conditionnelle, consommation, temps de fonctionnement). C'est le type de formule à utiliser pour : filtres horaires complexes (HP/HC/Pointe), alarmes comparatives (J-7, S-1), moyennes dynamiques tolérantes aux capteurs absents, ou toute logique conditionnelle avancée.
Vérifiez qu'un type natif ne suffit pas : une simple addition ou un ratio se font mieux en formule Arithmétique, un delta de compteur en formule Consommation. Les types natifs sont plus performants et plus robustes que du Python custom. Voir les types de formules.
Un prompt d'assistant IA est mis à votre disposition pour vous aider à créer vos formules Python (règles d'or, patterns prod, génération de code prêt à l'emploi). Voir la section Assistant IA — Aide à la rédaction de formules en fin de page.
L'interface d'édition
L'éditeur de formule Python s'organise autour de trois onglets : Paramètres, Éditeur & Test et Analytique.
Onglet Paramètres
Cet onglet liste les variables et constantes que votre code Python pourra utiliser. Chaque ligne définit un input (variable source ou constante) avec sa source, son mode de récupération, son agrégation et son unité.
Le bloc de gauche permet aussi de choisir le pas de temps de sortie (Temporel ou Synchronisé) — voir Le pas de temps de sortie pour le détail des deux modes.
Onglet Éditeur & Test
C'est ici que vous écrivez votre code Python. L'éditeur de code occupe la partie gauche, le panneau Résultats du Test la partie droite.

Le bouton Exécuter en haut à droite lance le code sur la plateforme et affiche le résultat dans le panneau de droite. Vous pouvez choisir le timestamp de déclenchement avec le sélecteur de date à côté du bouton, ce qui permet de tester la formule sur des données historiques.
Sous la zone de code, trois boutons (Importer un fichier, Exporter le fichier, Effacer) permettent de gérer directement le fichier .py.
Onglet Analytique
Une fois la formule fonctionnelle, l'onglet Analytique affiche un graphique comparant le résultat de votre formule aux variables d'entrée sur la période choisie, ainsi que les KPI agrégés en haut (dernière valeur, moyenne, minimum, maximum).

Cette vue permet de valider visuellement le comportement de la formule avant de la mettre en production.
Modèle d'exécution
Une formule Python reçoit ses données via un objet input et doit retourner une valeur scalaire unique (nombre, booléen, chaîne ou None) à chaque déclenchement. Les DataFrames reçus sont en lecture seule.
Accès aux variables d'entrée — chaque variable est un DataFrame pandas avec deux colonnes timestamp (datetime64) et value (float64). On y accède par attribut ou comme dans un dictionnaire :
# Accès par attribut (le plus courant)
input.temperature
# Accès style dictionnaire
input['temperature']
# Dernière valeur d'une variable
input.temperature['value'].iloc[-1]
# Itération sur l'historique
for i in range(len(input.temperature)):
ts = input.temperature['timestamp'].iloc[i]
v = input.temperature['value'].iloc[i]
Explorer l'objet input — il se manipule comme un dictionnaire :
| Méthode | Description |
|---|---|
input.keys() | Noms de toutes les variables d'entrée |
input.values() | Tous les DataFrames |
input.items() | Paires (nom, DataFrame) |
len(input) | Nombre de variables d'entrée |
'temperature' in input | Teste l'existence d'une variable |
Itérer directement sur input parcourt les noms des variables, pas les DataFrames :
for name in input: # name = nom de la variable
df = input[name] # récupérer le DataFrame correspondant
Accès aux constantes — une constante est un scalaire directement utilisable :
surface = input.surface # PAS input.surface['value'].iloc[-1]
Variable globale timestamp — pd.Timestamp en UTC, représente le moment où la formule est déclenchée :
_hour = timestamp.hour
_month = timestamp.month
_wd = timestamp.dayofweek + 1 # 1 = Lundi ... 7 = Dimanche
Retour — la valeur finale est renvoyée par return. Elle doit être scalaire :
return 42.5 # numérique
return 100 # entier
return "high" # chaîne
return True # booléen / alarme (0 ou 1)
return None # aucun résultat
Sont interdits en retour : DataFrame, Series, liste, dict. Pour signaler une absence de donnée, renvoyez 0, une valeur sentinelle (-1) ou None.
Librairies disponibles
Les librairies suivantes sont pré-importées (pas de import à écrire) :
| Librairie | Alias | Usage |
|---|---|---|
| pandas | pd | DataFrames, Series, Timestamp, Timedelta |
| numpy | np | Fonctions mathématiques (sqrt, exp, log, sin, cos…) |
| time | time | Module standard Python |
Tout autre import est interdit (datetime, pytz, math, re…). Pour la gestion des fuseaux horaires DST, voir l'exemple "Filtre horaire HP/HC" ci-dessous.
Exemples de formules
Exemple 1 — Retransmettre une valeur (pass-through)
Le plus basique : recopier la dernière valeur d'une source.
if len(input.source) == 0:
return 0
return input.source['value'].iloc[-1]
Exemple 2 — Ratio avec protection division par zéro
Calculer le ratio entre deux variables en évitant une division par zéro.
if len(input.numerateur) == 0 or len(input.denominateur) == 0:
return 0
num = input.numerateur['value'].iloc[-1]
den = input.denominateur['value'].iloc[-1]
if den == 0:
return 0
return num / den * 100 # pourcentage
Exemple 3 — Filtre horaire HP/HC (DST-aware Europe/Paris)
Ne retransmettre la valeur que pendant les Heures Creuses (22h-6h en semaine et samedi, dimanche entier). La conversion DST UTC → heure locale est faite manuellement.
if len(input.source) == 0:
return 0
val = input.source['value'].iloc[-1]
# Calcul du décalage DST pour Europe/Paris
_year = timestamp.year
_last_mar = pd.Timestamp(f'{_year}-03-31')
_dst_start_day = 31 - (_last_mar.dayofweek + 1) % 7
_dst_start_utc = pd.Timestamp(f'{_year}-03-{_dst_start_day:02d} 01:00:00')
_last_oct = pd.Timestamp(f'{_year}-10-31')
_dst_end_day = 31 - (_last_oct.dayofweek + 1) % 7
_dst_end_utc = pd.Timestamp(f'{_year}-10-{_dst_end_day:02d} 01:00:00')
_offset = 2 if _dst_start_utc <= timestamp < _dst_end_utc else 1
_ts_local = timestamp + pd.Timedelta(hours=_offset)
_hour = _ts_local.hour
_wd = _ts_local.dayofweek + 1 # 1=Lun ... 7=Dim
is_hc = (_wd <= 6 and (_hour >= 22 or _hour < 6)) or (_wd == 7)
if is_hc:
return val
return 0
Exemple 4 — Somme dynamique multi-inputs
Sommer plusieurs variables en gérant les capteurs absents ou en panne. Utile pour une consommation totale calculée à partir de sous-compteurs dont certains peuvent ne pas exister sur tous les sites.
inputs_a_sommer = ['meter1', 'meter2', 'meter3', 'meter4']
total = 0.0
for name in inputs_a_sommer:
if name in input and len(input[name]) > 0:
v = input[name]['value'].iloc[-1]
if not pd.isna(v):
total += float(v)
return total
Limitations et contraintes
Le service d'exécution impose des limites strictes :
| Contrainte | Valeur |
|---|---|
| Temps d'exécution | 0,5 seconde maximum (par défaut) |
| Imports externes | Aucun (pd, np, time uniquement) |
| Accès aux données | DataFrames en lecture seule |
| Valeur de retour | Scalaire uniquement (pas de DataFrame, Series, liste…) |
Gardez vos scripts simples et rapides : au-delà de 0,5 s, l'exécution est interrompue.
Référence technique
Le moteur d'exécution Python utilise une émulation custom de pandas/numpy. Certaines fonctionnalités du Python standard ne fonctionnent pas. Voici les règles principales à respecter :
Retour de formule
- Toujours retourner une valeur scalaire :
return 42,return 0,return True - Jamais de DataFrame, liste, dict ou Series en retour
- Pour signaler "pas de donnée", retourner
0ou une valeur sentinel (-1)
Imports
- Aucun
import:pd,np,timesont déjà disponibles datetime,pytz,math,re: indisponibles → utiliser les équivalents pandas/numpy
Accès aux données
- Toujours vérifier qu'un input n'est pas vide :
if len(input.X) == 0: return 0 - Les constantes sont des scalaires :
input.surfacedirectement, sans['value'].iloc[-1] - Ne jamais utiliser
dir(input)(crash) → utiliserinput.keys() - Ne jamais utiliser
.valuessur une Series → utiliserlist(series)
Manipulation des timestamps
.dt.year,.dt.month,.dt.day,.dt.dayofweek: OK.dt.hour,.dt.minute,.dt.floor(),.dt.normalize(): ne fonctionnent pas → utiliser.apply(lambda ts: ts.hour)oustr(ts)[:13]- Ne jamais soustraire un
pd.Timedeltaà la variable globaletimestamp(TypeError) → soustraire entre timestamps existants
Numpy
- OK :
np.array,np.sqrt,np.exp,np.log,np.abs,np.isnan,np.nan,np.pi - Plantent :
np.where,np.ones,np.zeros,np.minimum,np.maximum,np.mean,np.sum→ utiliser un ternaire Python,min(),max(), ou les méthodes Series (.mean(),.sum())
Assistant IA — Aide à la rédaction de formules (Beta)
Cet assistant est en cours de test. Les règles et patterns proposés sont issus de cas de production réels, mais peuvent évoluer après les mises à jour de la plateforme. Toujours valider la formule générée avec une simulation sur la plateforme avant de la mettre en production.
Pour vous aider à rédiger vos formules Python, nous mettons à disposition un prompt d'assistant IA compatible avec Claude, ChatGPT, Gemini ou tout autre LLM. Ce prompt transforme l'assistant en expert de la création de formules Python sur la plateforme Datamonk / GraalPython.
Ce que l'assistant vous apporte
- Règles d'or et pièges propres à l'émulation GraalPython (pandas/numpy limités, accesseur
.dtpartiel, manipulation des timestamps, etc.) - Catalogue de patterns prêts à l'emploi : pass-through, ratio, filtre HP/HC DST-aware, alarme J-7, somme dynamique multi-inputs, métronome, etc.
- Génération de code : décrivez votre besoin métier, l'assistant pose 1-2 questions de clarification puis fournit le code Python + la configuration des inputs et du pas de temps de sortie
- Debugging : il peut diagnostiquer une formule qui ne fonctionne pas en production
Mode d'emploi
- Téléchargez le prompt : assistant-formule-python.md
- Ouvrez une nouvelle conversation avec votre assistant IA préféré (Claude, ChatGPT, Gemini, etc.)
- Collez l'intégralité du contenu du fichier comme premier message (ou comme system prompt si l'outil le permet)
- Décrivez votre besoin : « Je veux une formule qui calcule la consommation HP entre 6h et 22h hors weekend pour un compteur électrique. »
- L'assistant vous fournira la formule Python prête à coller dans l'éditeur, avec la configuration des inputs et du pas de temps de sortie correspondants
Nos tests internes montrent une performance améliorée avec Claude (Anthropic), notamment sur le respect des règles GraalPython et la qualité du code généré. Les autres assistants (ChatGPT, Gemini, etc.) fonctionnent également et donnent de bons résultats, mais peuvent demander un peu plus d'allers-retours pour affiner la formule.
Plus vous donnez de contexte (nom des variables disponibles, fréquence souhaitée, format de sortie attendu), plus la formule générée sera prête à l'emploi.
