it-swarm.com.de

Abbruch-Threading.Timer in Python

Ich versuche, eine Methode zu schreiben, die bis zu einer bestimmten Zeit heruntergezählt wird. Wenn kein Neustartbefehl gegeben wird, führt er die Task aus. Aber ich glaube nicht, dass die Klasse Python threading.Timer den Timer abbrechen kann.

import threading

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

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

    t.start()

Ich weiß, dass der obige Code irgendwie falsch ist. Würde mich über eine freundliche Anleitung freuen.

30
Ted

Sie würden die Abbruchmethode aufrufen, nachdem Sie den Timer gestartet haben:

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

Sie können die Verwendung einer while-Schleife für einen Thread anstelle eines Timer in Betracht ziehen.
Hier ist ein Beispiel, das von Nikolaus Gradwohl answer auf eine andere Frage angewendet wurde:

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

Ich bin mir nicht sicher, ob ich es richtig verstanden habe. Möchten Sie so etwas wie in diesem Beispiel schreiben?

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

Die threading.Timer-Klasse does hat eine cancel-Methode, und obwohl sie den thread nicht abbricht, stoppt sie den Timer. Was tatsächlich passiert, ist, dass die cancel-Methode einen threading.Event setzt und der Thread, der den threading.Timer ausführt, das Ereignis überprüft, nachdem das Warten beendet wurde und bevor der Callback tatsächlich ausgeführt wird.

Das heißt, Timer werden normalerweise ohne implementiert, wobei für jeden ein eigener Thread verwendet wird. Der beste Weg, dies zu tun, hängt davon ab, was Ihr Programm tatsächlich tut (während Sie auf diesen Timer warten), aber alles, was über eine Ereignisschleife wie GUI und Netzwerk-Frameworks verfügt, hat alle Möglichkeiten, einen Timer anzufordern, der mit dem Eventloop verbunden ist.

7
Thomas Wouters

Inspiriert durch den obigen Beitrag . Abbruch und Zurücksetzen des Timers in Python. Es verwendet Thread.
Funktionen: Start, Stopp, Neustart, Rückruffunktion.
Eingabe: Timeout, sleep_chunk-Werte und Callback-Funktion.
Kann diese Klasse in einem anderen Programm verwenden oder erben. Kann auch Argumente an die Rückruffunktion übergeben.
Timer sollte auch in der Mitte antworten. Nicht erst nach dem vollen Schlaf. Anstatt einen vollen Schlaf zu verwenden, verwenden Sie kleine Schlafabschnitte und prüfen das Ereignisobjekt ständig in der Schleife.

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