web-dev-qa-db-fra.com

Filetage annulable. Minuteur en Python

J'essaie d'écrire une méthode qui compte à rebours à un moment donné et à moins qu'une commande de redémarrage ne soit donnée, il exécutera la tâche. Mais je ne pense pas que la classe Python threading.Timer permette l'annulation du minuteur.

import threading

def countdown(action):
    def printText():
        print 'hello!'

    t = threading.Timer(5.0, printText)
    if (action == 'reset'):
        t.cancel()

    t.start()

Je sais que le code ci-dessus est faux en quelque sorte. J'apprécierais des conseils aimables par ici.

30
Ted

Vous appelez la méthode cancel après avoir démarré le chronomètre:

import time
import threading

def hello():
    print "hello, world"
    time.sleep(2)

t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
    t.cancel()

Vous pourriez envisager d'utiliser une boucle while sur un Thread , au lieu d'utiliser un Timer.
Voici un exemple approprié de Nikolaus Gradwohl's answer à une autre question:

import threading
import time

class TimerClass(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()
        self.count = 10

    def run(self):
        while self.count > 0 and not self.event.is_set():
            print self.count
            self.count -= 1
            self.event.wait(1)

    def stop(self):
        self.event.set()

tmr = TimerClass()
tmr.start()

time.sleep(3)

tmr.stop()
30
Honest Abe

Je ne suis pas sûr de bien comprendre. Voulez-vous écrire quelque chose comme dans cet exemple?

>>> import threading
>>> t = None
>>> 
>>> def sayHello():
...     global t
...     print "Hello!"
...     t = threading.Timer(0.5, sayHello)
...     t.start()
... 
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>
13
Adam

La classe threading.Timerfait a une méthode cancel et, bien qu'elle n'annule pas le thread, elle empêchera le chronomètre de se déclencher. En réalité, la méthode cancel définit un threading.Event et le thread qui exécute le threading.Timer vérifiera cet événement une fois l'attente terminée et avant l'exécution du rappel.

Cela dit, les timers sont généralement implémentés sans en utilisant un thread distinct pour chacun. La meilleure façon de le faire dépend de ce que votre programme est en train de faire (en attendant ce minuteur), mais tout ce qui a une boucle d’événement, telle que les interfaces graphiques et réseau, permet de demander un minuteur connecté au eventloop.

7
Thomas Wouters

Inspiré par le message ci-dessus . Annulable et réinitialisation du minuteur en Python. Il utilise du fil.
Caractéristiques: Démarrer, Arrêter, Redémarrer, fonction de rappel.
Entrée: valeurs de délai d’attente, sleep_chunk et callback_function.
Peut utiliser ou hériter de cette classe dans n’importe quel autre programme. Peut également passer des arguments à la fonction de rappel.
La minuterie devrait répondre au milieu aussi. Pas juste après la fin du temps de sommeil complet. Ainsi, au lieu d’utiliser un seul sommeil complet, utilisez de petits morceaux de sommeil et gardez l’objet de vérification en boucle.

import threading
import time

class TimerThread(threading.Thread):
    def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
        threading.Thread.__init__(self)

        self.timeout = timeout
        self.sleep_chunk = sleep_chunk
        if callback == None:
            self.callback = None
        else:
            self.callback = callback
        self.callback_args = args

        self.terminate_event = threading.Event()
        self.start_event = threading.Event()
        self.reset_event = threading.Event()
        self.count = self.timeout/self.sleep_chunk

    def run(self):
        while not self.terminate_event.is_set():
            while self.count > 0 and self.start_event.is_set():
                # print self.count
                # time.sleep(self.sleep_chunk)
                # if self.reset_event.is_set():
                if self.reset_event.wait(self.sleep_chunk):  # wait for a small chunk of timeout
                    self.reset_event.clear()
                    self.count = self.timeout/self.sleep_chunk  # reset
                self.count -= 1
            if self.count <= 0:
                self.start_event.clear()
                #print 'timeout. calling function...'
                self.callback(*self.callback_args)
                self.count = self.timeout/self.sleep_chunk  #reset

    def start_timer(self):
        self.start_event.set()

    def stop_timer(self):
        self.start_event.clear()
        self.count = self.timeout / self.sleep_chunk  # reset

    def restart_timer(self):
        # reset only if timer is running. otherwise start timer afresh
        if self.start_event.is_set():
            self.reset_event.set()
        else:
            self.start_event.set()

    def terminate(self):
        self.terminate_event.set()

#=================================================================
def my_callback_function():
    print 'timeout, do this...'

timeout = 6  # sec
sleep_chunk = .25  # sec

tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
tmr.start()

quit = '0'
while True:
    quit = raw_input("Proceed or quit: ")
    if quit == 'q':
        tmr.terminate()
        tmr.join()
        break
    tmr.start_timer()
    if raw_input("Stop ? : ") == 's':
        tmr.stop_timer()
    if raw_input("Restart ? : ") == 'r':
        tmr.restart_timer()
0
manohar