APScheduler : tes scripts Python tournent tout seuls, même quand tu dors

APScheduler : tes scripts Python tournent tout seuls, même quand tu dors

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom": "APScheduler", "version": "3.11.3"}

Difficulté

Débutant

Combien de fois tu relances le même script à la main ? Le récap du matin, la sauvegarde du dimanche, la vérification de l'API toutes les quinze minutes. À force, tu finis par oublier, ou par te lever exprès pour appuyer sur Entrée. APScheduler met fin à ce cirque : c'est une bibliothèque Python qui planifie des fonctions comme le ferait cron, mais directement dans ton code, sans toucher au crontab du système.

Le principe est simple. Tu écris une fonction Python normale, tu la confies à un planificateur avec un déclencheur, et il se charge de l'appeler au bon moment : toutes les cinq secondes, chaque lundi à 8 h 30, le premier du mois, ou n'importe quelle combinaison. Dans ce tutoriel, on monte un planificateur de zéro, avec des exemples qui tournent vraiment.

Installe APScheduler

Comme toujours, on travaille dans un environnement virtuel pour ne pas polluer ton système.

bash
python -m venv .venv
source .venv/bin/activate
pip install apscheduler

La bibliothèque s'appelle apscheduler sur PyPI. Aucune dépendance exotique : elle tourne partout où Python 3 tourne.

Ta première tâche, toutes les cinq secondes

Le planificateur le plus simple s'appelle BlockingScheduler. Il prend la main sur le programme et boucle jusqu'à ce que tu l'arrêtes. Ici, on lance une fonction toutes les cinq secondes :

python
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def bonjour():
    print(f"[{datetime.now():%H:%M:%S}] Tâche exécutée")

scheduler = BlockingScheduler()
scheduler.add_job(bonjour, "interval", seconds=5)
scheduler.start()

add_job prend trois arguments : la fonction, le type de déclencheur ("interval"), puis ses paramètres. Ici, seconds=5. La boucle bloque le script : pour l'arrêter, un Ctrl+C suffit.

Planifie comme un cron, à l'heure près

Pour du vrai ordonnancement calendaire, on passe à CronTrigger. Même logique qu'un crontab, mais avec des mots clés lisibles : hour, minute, day_of_week, day, month. Exemple : générer un récap chaque jour ouvré à 8 h 30.

python
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger

def recap_du_matin():
    print("Génération du récap du matin")

scheduler = BlockingScheduler()
scheduler.add_job(
    recap_du_matin,
    CronTrigger(hour=8, minute=30, day_of_week="mon-fri"),
)
scheduler.start()

day_of_week="mon-fri" couvre du lundi au vendredi. Tu peux écrire minute="*/10" pour toutes les dix minutes, hour="0,12" pour minuit et midi, ou day="1" pour le premier du mois. Les plages, les listes et les pas se combinent librement.

Un cas réel : surveiller une API en arrière-plan

BlockingScheduler bloque tout, ce qui ne colle pas si ton programme a autre chose à faire. BackgroundScheduler exécute les tâches dans des threads séparés et te rend la main. Cas classique : vérifier qu'une API répond, et alerter dès que ça casse.

python
import time
import requests
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger

def verifier_api():
    reponse = requests.get("https://api.exemple.com/status", timeout=10)
    if reponse.status_code != 200:
        print(f"Alerte : l'API répond {reponse.status_code}")

scheduler = BackgroundScheduler()
scheduler.add_job(verifier_api, IntervalTrigger(minutes=15))
scheduler.start()

# Ton programme continue de tourner ici
try:
    while True:
        time.sleep(1)
except (KeyboardInterrupt, SystemExit):
    scheduler.shutdown()

Ici, verifier_api est appelée toutes les quinze minutes pendant que ton script continue de vivre dans sa boucle. Remplace l'URL par la tienne : un endpoint de santé, une file de messages à vider, un dossier à scanner. L'alerte peut être un email, un message Slack ou un simple log.

Survivre au redémarrage avec SQLite

Par défaut, les jobs sont stockés en mémoire : si ton script plante, tout est perdu. Pour que le planning survive à un redémarrage, on branche un job store SQLAlchemy sur un fichier SQLite.

python
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.triggers.cron import CronTrigger

def sauvegarde_quotidienne():
    print("Sauvegarde lancée")

jobstores = {"default": SQLAlchemyJobStore(url="sqlite:///jobs.sqlite")}
scheduler = BackgroundScheduler(
    jobstores=jobstores,
    executors={"default": ThreadPoolExecutor(4)},
)
scheduler.add_job(
    sauvegarde_quotidienne,
    CronTrigger(hour=2, minute=0),
    id="sauvegarde",
    replace_existing=True,
)
scheduler.start()

Une subtilité importante : avec la persistance, il faut une fonction nommée, pas un lambda. APScheduler doit pouvoir retrouver la référence de ta fonction pour la sérialiser, sinon il lève une erreur. L'id et replace_existing=True évitent de dupliquer le job si tu relances le script.

Conclusion

APScheduler, c'est le chaînon qui transforme un script jetable en petit service autonome. Pas de démon à configurer, pas de crontab à maintenir sur chaque machine : la planification vit dans ton code, versionnée avec le reste du projet. Commence par un interval de cinq secondes pour comprendre le mécanisme, puis branche un CronTrigger sur tes vraies tâches. Tu ne lanceras plus jamais rien à la main.

K

Auteur

Krugz

Développeur fullstack

Développeur fullstack qui tente, tant bien que mal, de suivre l'actualité de l'IA au milieu d'une marée d'informations imbuvables et des milliers d'outils et de modèles qui sortent chaque jour.