Table des matières

Comment appeler une fonction périodiquement (toutes les x secondes)

Objectif

On voudrait qu'une fonction puisse être appelée toutes les x secondes avec les caractéristiques suivantes:

Codage proposé

On utilise ici un thread qui lance un Timer dans une boucle et qui attend que ce Timer se termine (.join()). Une fois la durée d'attente prévue, le Timer lance la fonction avec les arguments définis et se termine, ce qui permet la relance d'un nouveau Timer.

L'appel à la méthode stop() permet d'arrêter un éventuel Timer en cours d'attente et d'empêcher une nouvelle boucle: le thread s'arrête donc.

Tel que programmée, la classe peut être placée dans un module.

On peut sans difficulté modifier la durée de l'intervalle “à la volée”. Il suffit d'affecter une autre valeur à t.duree, qui sera prise en compte à la prochaine boucle.

import threading
 
class Intervallometre(threading.Thread):
 
    def __init__(self, duree, fonction, args=[], kwargs={}):
        threading.Thread.__init__(self)
        self.duree = duree
        self.fonction = fonction
        self.args = args
        self.kwargs = kwargs
        self.encore = True  # pour permettre l'arret a la demande
 
    def run(self):
        while self.encore:
            self.timer = threading.Timer(self.duree, self.fonction, self.args, self.kwargs)
            self.timer.setDaemon(True)
            self.timer.start()
            self.timer.join()
 
    def stop(self):
        self.encore = False  # pour empecher un nouveau lancement de Timer et terminer le thread
        if self.timer.isAlive():
            self.timer.cancel()  # pour terminer une eventuelle attente en cours de Timer

Utilisation


Voilà 3 exemples de fonctions à appeler avec plusieurs façons de coder les arguments:

def affiche(ch, x="machin", y="truc"):
    print "top" + ' ' + ch + ' ' + x + ' ' + y
 
def affiche2(*args, **kwargs):
    ch = "top"
    ch += ' ' + args[0]
    ch += ' ' + kwargs['x']
    ch += ' ' + kwargs['y']
    print ch
 
def affiche3(*args, **kwargs):
    ch = "top"
    for arg in args:
        ch += ' ' + arg
    d = kwargs.items()
    d.sort()
    for cle, valeur in d:
        ch += ' ' + valeur
    print ch


Et voilà comment on appelle l'intervallometre:

import time
 
duree = 0.5
 
t =  Intervallometre(duree, affiche, ["toto"], {'x':"titi", 'y':"tata"})
t.setDaemon(True)
t.start()
 
time.sleep(5.1)
t.stop()
 
t2 =  Intervallometre(duree, affiche2, ["toto2"], {'x':"titi", 'y':"tata"})
t2.setDaemon(True)
t2.start()
 
time.sleep(5.1)
t2.stop()
 
t3 =  Intervallometre(duree, affiche3, ["toto3"], {'x':"titi", 'y':"tata"})
t3.setDaemon(True)
t3.start()
 
time.sleep(5.1)
t3.stop()


ce qui affichera:

top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto2 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata
top toto3 titi tata


Amusez-vous bien!