>_ DevTrendsfr

Langue

Accueil

Langages

Sections

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embarqué Sécurité
Python

Comment planifier des tâches en Python sans Celery et des solutions de contournement

Tout développeur backend y a probablement été confronté. Vous construisez un service web avec FastAPI ou Flask, le projet est encore petit, fonctionnant sur un seul serveur. Puis le chef de produit demande : « Hé, envoyons aux clients un résumé chaque matin à 9h, et réinitialisons les paniers expirés toutes les heures ? »

Le premier réflexe est d'ajouter Celery avec Celery Beat et Redis. Mais lancer un broker, configurer des workers et surveiller des démons juste pour deux tâches d'arrière-plan semble excessif. La deuxième option est le cron système, mais cela disperse la logique entre le code de l'application et la configuration du serveur. Vous voulez un planificateur intégré dans votre code, capable de gérer 2 tâches, et de s'adapter à plusieurs nœuds si nécessaire.

C'est là que la bibliothèque APScheduler (Advanced Python Scheduler) s'avère utile.

Ce que la bibliothèque peut faire

APScheduler existe depuis un certain temps, et le projet est actuellement en transition vers la version 4.0. La quatrième branche est encore en statut pré-release, mais elle a considérablement restructuré l'architecture de la bibliothèque.

Auparavant, c'était principalement un planificateur local pour un seul processus, mais maintenant l'outil a évolué en un système complet de file d'attente et de planification distribué. Le cas d'utilisation le plus simple s'exécute toujours en seulement trois lignes de code.

Le concept central : vous déclarez des fonctions Python ordinaires ou des coroutines et attachez un déclencheur avec les conditions d'exécution nécessaires.

La bibliothèque gère le suivi du temps, calcule les décalages et invoque les fonctions au bon moment.

Options de planification

Quatre types de déclencheurs intégrés sont disponibles :

  • Déclencheur cron. Syntaxe familière de style Linux. Vous pouvez définir de manière flexible les jours de la semaine, les mois, les heures et les minutes spécifiques.
  • Intervalles. Exécuter toutes les N secondes, minutes ou heures. Utile pour interroger régulièrement des API externes.
  • Déclencheur calendrier. Nécessaire lorsque l'intervalle dépend de la durée d'un mois ou d'une année. Par exemple, exécuter une tâche strictement le premier jour de chaque mois à midi.
  • Exécution unique. Se déclenche exactement une fois à une date et une heure futures spécifiées.

Si les conditions intégrées ne suffisent pas, les déclencheurs peuvent être combinés à l'aide de règles composées ou vous pouvez écrire votre propre classe avec une logique personnalisée.

Protection contre les échecs courants

En pratique, les tâches d'arrière-plan rencontrent régulièrement des surcharges et des retards. APScheduler inclut plusieurs mécanismes utiles qui sont souvent négligés dans les solutions personnalisées construites sur 3 et 4.

Premièrement, la limitation des exécutions simultanées. Si vous avez configuré une exportation de rapport lourde toutes les cinq minutes, mais que l'exécution précédente s'est bloquée pendant sept minutes, le planificateur ne lancera pas une deuxième instance en parallèle et ne surchargera pas la base de données.

Deuxièmement, le paramètre 5. Il ajoute un délai aléatoire au moment de début de la tâche. Imaginez que vous avez une centaines de workers, et qu'ils doivent tous actualiser le cache à exactement 00:00. Sans gigue, la base de données recevra un pic de charge instantané. Avec un décalage aléatoire de quelques secondes, la charge est distribuée uniformément.

Troisièmement, la gestion du temps de grâce pour les tâches manquées. Si le serveur s'est figé sous la charge ou était en cours de redémarrage, le planificateur vérifie le retard de la tâche. Si le délai correspond à la limite acceptable, la tâche s'exécutera ; sinon, elle sera ignorée sans accumulation dans la file d'attente.

Stockage et mode distribué

Pour les scripts simples, les tâches peuvent être conservées en mémoire. Mais si le service redémarre, la planification sera réinitialisée. Pour éviter cela, la bibliothèque prend en charge le stockage persistant :

  • PostgreSQL
  • MySQL
  • SQLite
  • MongoDB

Dans la version quatre, le planificateur a appris à fonctionner dans un cluster distribué. Plusieurs instances d'application se connectent à une base de données partagée et à un broker d'événements (Redis, PostgreSQL LISTEN/NOTIFY et MQTT sont pris en charge).

Cela permet une mise à l'échelle horizontale : un nœud tombe en panne, les autres reprennent les tâches de la file d'attente.

Code synchrone et asynchrone

La bibliothèque s'intègre bien dans la pile Python moderne. Différentes implémentations de planificateur sont disponibles :

  • 6 et intégration avec Trio pour les backends asynchrones modernes comme FastAPI, Litestar ou Aiohttp.
  • 7 et 8 pour les scripts synchrones, Django et Flask.

Vous n'avez pas besoin d'envelopper les fonctions asynchrones dans des contournements synchrones avec 9 — le planificateur attend nativement les coroutines à l'intérieur de la boucle d'événements principale.

Où cela s'avère utile

J'utilise généralement APScheduler dans trois situations typiques :

  1. Petits microservices et bots. Lorsque le déploiement de Celery ou RQ serait excessif, et que des tâches périodiques sont nécessaires directement dans le processus.
  2. Actions utilisateur différées. Par exemple, envoyer un e-mail demandant de noter une commande exactement 24 heures après la livraison.
  3. Nettoyage des données temporaires et synchronisation périodique des données de référence provenant de systèmes externes.

Cela vaut-il la peine d'être utilisé dans un projet

Si vous écrivez en Python et avez besoin d'une exécution de tâches basée sur le temps prévisible, APScheduler est l'une des options les plus matures.

La seule nuance actuellement : la période de transition entre les versions 3.x et 4.0. La troisième branche a été testée en production pendant des années, est максимально stable, mais présente des limites dans le fonctionnement distribué. La version 4.0 apporte une architecture moderne et une mise à l'échelle, mais l'auteur avertit honnêtement des éventuels changements d'API cassants avant la version finale.

Pour la production actuelle, il est plus sûr de s'en tenir à la branche stable 10, et la version 4.0 mérite d'être essayée dans des projets personnels ou de nouveaux microservices tout en surveillant les changements à venir.

Projets similaires