2012-03-21 17 views
23

Estoy tratando de escribir un método que cuente hacia abajo en un momento dado y, a menos que se dé un comando de reinicio, ejecutará la tarea. Pero no creo que la clase Python threading.Timer permita que el temporizador sea cancelable.Enhebrado cancelable.Timer en Python

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 es incorrecto de alguna manera. Agradecería una guía amable por aquí.

Respuesta

12

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

Es _ casi_ bueno. Sería * bueno * si su programa no terminara inmediatamente, con un solo "Hola" y sin demora alguna. :) Tienes que incorporar 't.cancel()' en la función 'sayHello()' en función de alguna condición, p. 'if counter == 10: t.cancel()'. Entonces tendría un significado. – Apostolos

+0

Lo siento. No sería bueno incluso entonces. Si agrega un código después de llamar a 'sayHello (0)', ¡se ejecutará antes de que termine la prueba del temporizador! (Inténtelo usted mismo, agregando, por ejemplo, 'print" Done "' al final de su código.) – Apostolos

25

Se podría llamar al método cancelar 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() 

usted podría considerar el uso de un bucle while en un Thread, en lugar de utilizar un temporizador .
Aquí es un ejemplo apropiado de Nikolaus Gradwohl de answer 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() 
+0

Explique por qué cree que un ciclo while while es una mejor idea que el temporizador con rosca. –

+1

@WesModes Ofrecí una alternativa que imprime la cuenta regresiva. –

+0

Funciona para mí. Aunque utilicé mientras no self.event.wait (1) para ejecutar algo cada segundo en lugar de una variable de conteo – mtosch

6

La clase threading.Timer no tiene un método cancel, y aunque no se cancelará la hilo, se detendrá el temporizador de realmente disparar. Lo que realmente ocurre es que el método cancel establece un threading.Event, y el hilo que realmente ejecuta el threading.Timer verificará ese evento una vez que haya terminado de esperar y antes de que realmente ejecute la devolución de llamada.

Dicho esto, los temporizadores generalmente se implementan sin usando una cadena separada para cada uno. La mejor manera de hacerlo depende de lo que realmente está haciendo tu programa (mientras esperas este temporizador), pero cualquier cosa con un bucle de eventos, como la GUI y los marcos de red, todos tienen formas de solicitar un temporizador que esté enganchado en eventloop.

0

Inspirado por la publicación anterior. Cancelable y restablecer el temporizador en Python. Utiliza hilo
Funciones: inicio, parada, reinicio, función de devolución de llamada.
Entrada: tiempo de espera, valores sleep_chunk y callback_function.
Se puede usar o heredar esta clase en cualquier otro programa. También puede pasar argumentos a la función de devolución de llamada.
El temporizador debe responder también en el medio. No solo después de completar el tiempo de sueño completo. Entonces, en lugar de usar un sueño completo, usar pequeños trozos de sueño y seguir revisando el 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()