On voudrait qu'une fonction puisse être appelée toutes les x secondes avec les caractéristiques suivantes:
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
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!