Récupérer des données en temps réel: Schedule
Dans cette quête, tu vas apprendre à programmer le lancement d'un script.

Objectifs
- Programmer l'exécution d'un script à une date/heure données
- Programmer l'exécution d'un script récurrent toutes X minutes
Installation et import de Schedule
Pour programmer le l'exécution d'un script, Python inclut la bibliothèque schedule.
Si schedule n'est pas installé par défaut, il te suffit d'exécuter la commande suivante. Nous t'invitons à essayer tous les codes suivants dans un notebook, en lisant la quête en parallèle.
!pip install schedule
Tu pourras maintenant importer schedule dans ton script :
import schedule
import time
Fonctionnement
Le but de la bibliothèque schedule est de pouvoir :
- soit lancer un script à une heure fixée à l'avance, par exemple demain à 18h30
- ou bien de lancer un script toutes les X période de temps, par exemple toutes les heures.
Nous allons commencer par cette seconde option.
Le process sera le suivant :
- Définition d'une fonction qui fera une action
- Paramétrage de schedule pour se lancer toutes les X périodes de temps
- Lancement du schedule, qui exécutera la fonction (1) à l'horaire choisi (2)
- Puis le script se mettra en veille jusqu'à la prochaine exécution
Pour que cela fonctionne, le script python ne doit pas être arrêté. Il doit être en veille.
- S'il est arrêté, il ne peut pas se lancer tout seul (c'est plutôt rassurant pour la sécurité de ton ordinateur).
- S'il est en veille, il peut alors se réveiller puis se rendormir.
Commençons donc par définir une fonction, qui fera une action assez simple : afficher l'heure au moment de l'exécution du script.
from datetime import datetime
def current_time():
now = datetime.now()
print("What is the current time ?", now.strftime("%H:%M:%S"))
Tu peux exécuter la fonction pour vérifier qu'elle fonctionne bien :
current_time()
>>> What is the current time ? 10:33:23
Nous allons maintenant définir notre schedule pour qu'il se lance toutes les 10 secondes.
- Tout d'abord nous définissons la période avec
every(10).secondset nous indiquons au schedule ce qu'il doit faire lorsque l'horaire arrive. Nous lui indiquons alors le nom de notre fonction précédemment définiecurrent_time. Tu peux évidemment lui mettre la fonction de ton choix. - Ensuite, nous créons une boucle infinie (tu aurais pu mettre une condition pour que la boucle s'arrête), pour indiquer à
schedulede systématiquement faire la même action.
schedule.every(10).seconds.do(current_time)
while True:
schedule.run_pending()
time.sleep(1)
>>> What is the current time ? 10:35:41
>>> What is the current time ? 10:35:51
>>> What is the current time ? 10:36:01
...
Comme il s'agit ici d'une boucle infinie, avec 10 secondes de "veille" entre chaque, tu dois stopper le traitement manuellement quand tu veux qu'il s'arrête.
Ajout d'un second traitement et nettoyage des tâches
La boucle demande à schedule d'effectuer les "tâches" indiquées. Nous pouvons ajouter de nouvelles tâches, simplement en ajoutant une fonction dans do. Mais attention, les tâches précédemment indiquées continueront à s'exécuter ! (même si on ne les indique pas de nouveau).
def hello():
print("hello, how are you?")
schedule.every(10).seconds.do(hello)
while True:
schedule.run_pending()
time.sleep(1)
>>> What is the current time ? 10:44:29
>>> hello, how are you?
>>> What is the current time ? 10:44:39
>>> hello, how are you?
>>> What is the current time ? 10:44:49
Tu dois donc parfois faire du ménage, pour ne pas exécuter toutes les tâches en double. Commence par observer les tâches ("jobs") qui sont en mémoire :
schedule.jobs
[Every 10 seconds do current_time() (last run: 2021-01-21 10:44:49, next run: 2021-01-21 10:44:59),
Every 10 seconds do hello() (last run: 2020-11-21 10:44:49, next run: 2020-11-21 10:44:59)]
On observe bien qu'il y a 2 tâches en mémoire :
- une première qui exécute
current_timetoutes les 10 secondes - une seconde qui exécute
hellotoutes les 10 secondes également
Tu peux nettoyer toutes les tâches avec la fonction schedule.clear().
Exécution à une heure précise
Pour exécuter à une heure précise, la syntaxe est presque identique :
schedule.every().day.at("10:55").do(current_time)
while True:
schedule.run_pending()
time.sleep(1)
Attention, il faut indiquer une heure GMT, du fuseau horaire de Greenwich (de Londres aussi :) ).
Tape sur Google time gmt pour connaitre l'heure actuelle.
Tu peux même choisir le jour de la semaine pour lancer le traitement, par exemple, tous les mercredis à 16h :
schedule.every().wednesday.at("16:00").do(current_time)
while True:
schedule.run_pending()
time.sleep(1)
Avec différents exemples sur les formats d'heures
Cas d'usage
La programmation des traitements est très souvent utilisée. Quelques exemples :
- lancements de traitements lourds, risquant de ralentir les serveurs : nous préférons alors les lancer la nuit, quand aucun employé ne travaille. Mais personne n'a très envie de lancer un traitement à minuit, alors on le programme à l'avance.
- reporting : une actualisation des requêtes SQL et des graphiques d'un tableau de bord pour l'envoyer automatiquement tous les lundis matin à 9h.
- récupération de données périodiques : un thermomètre connecté qui te donne la température en temps réel, mais ne stocke pas l'historique. Tu vas lancer un traitement automatique toutes les heures qui va collecter l'information et la stocker, sans intervention humaine.
- scraping : certains sites bloquent les requêtes trop rapides, identifiées comme un robot. Tu peux alors espacer chaque requête d'une seconde pour éviter une saturation/un blocage.
Déploiement
Afin d'automatiser ces traitements, par exemple pour collecter des données toutes les heures, tu ne pourras pas rester sur Google Colab. Car Google réinitialise régulièrement ses serveurs. Ton traitement sera donc stoppé, et tes données risquent d'être perdues. La meilleure solution serait de passer par une solution cloud, mais les solutions cloud sont souvent payantes.
Le plus simple reste encore de lancer ce script en local, sur ta machine. Si tu ne sais pas lancer un script en local, tu peux aller voir la quête ci-dessous :
- Quête 1527 (hors archive)
Ton ordinateur et ton terminal devront rester allumés pendant toute la durée du traitement. Attention au réglage de la mise en veille de ton ordinateur. Par contre, si le traitement est léger, rien ne t'empêche de faire autre chose en parallèle, pense juste à laisser le terminal ouvert.
Ton traitement peut tomber en erreur. Pense donc à chaque tour de boucle (ou tous les 10 tours de boucle par exemple) à exporter les données dans un fichier. En effet, Python stocke les données dans la mémoire vive, mais cette mémoire est effacée s'il y a une erreur. Alors que si tu exportes les données, elles seront conservées
Validation
Cette quête de découverte est en auto-validation. Si tu as bien compris le fonctionnement, et bien suivi l'ensemble des consignes, tu peux la valider.