Roscado cancelable.Timer en Python

Estoy tratando de escribir un método que haga una cuenta regresiva en un momento dado y, a menos que se dé un comando de reinicio, ejecutará la tarea. Pero no creo que el threading.Timer Python. La clase de temporizador permite que el temporizador sea cancelable.

 import threading def countdown(action): def printText(): print 'hello!' t = threading.Timer(5.0, printText) if (action == 'reset'): t.cancel() t.start() 

Sé que el código anterior está mal de alguna manera. Apreciaría alguna orientación amable por aquí.

Llamarías al método de cancelación después de iniciar el temporizador:

 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() 

Podría considerar usar un bucle while en un hilo , en lugar de usar un temporizador .
Aquí hay un ejemplo apropiado de la respuesta de Nikolaus Gradwohl a otra pregunta:

 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() 

No estoy seguro si entiendo correctamente. ¿Quieres escribir algo como en este ejemplo?

 >>> 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() >>> 

La clase threading.Timer tiene un método de cancel , y aunque no cancelará el hilo , detendrá el temporizador para que no se dispare. Lo que realmente sucede es que el método de cancel establece un threading.Event . threading.Event , y el subproceso que realmente ejecuta el threading.Timer . El threading.Timer verificará ese evento después de que haya terminado de esperar y antes de que realmente ejecute la callback.

Dicho esto, los temporizadores generalmente se implementan sin utilizar un subproceso separado para cada uno. La mejor manera de hacerlo depende de lo que realmente esté haciendo su progtwig (mientras espera este temporizador), pero cualquier cosa con un bucle de eventos, como GUI y marcos de red, todos tienen formas de solicitar un temporizador que está conectado al evento.

Inspirado por el post anterior. Temporizador cancelable y de reinicio en Python. Utiliza hilo.
Características: Iniciar, detener, reiniciar, función de callback.
Entrada: Tiempo de espera, valores sleep_chunk y callback_function.
Puede usar o heredar esta clase en cualquier otro progtwig. También puede pasar argumentos a la función de callback.
El temporizador también debe responder en el medio. No solo después de completar el tiempo completo de sueño. Así que, en lugar de usar un modo de suspensión completo, utilice pequeños fragmentos de suspensión y mantenga el control del objeto de evento en bucle.

 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()