Отменять threading.Timer в Python
Я пытаюсь написать метод, который учитывается до заданного времени, и если не указывается команда перезапуска, она выполнит задачу. Но я не думаю, что класс Python threading.Timer
позволяет отменить таймер.
import threading
def countdown(action):
def printText():
print 'hello!'
t = threading.Timer(5.0, printText)
if (action == 'reset'):
t.cancel()
t.start()
Я знаю, что приведенный выше код неверен. Понадобились бы некоторые добрые указания здесь.
Ответы
Ответ 1
Вы можете вызвать метод отмены после запуска таймера:
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()
Вы можете использовать while-loop на Thread вместо использования таймера.
Вот пример, присвоенный Николаусом Градволем ответить на другой вопрос:
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()
Ответ 2
Я не уверен, правильно ли я понимаю. Вы хотите написать что-то вроде этого примера?
>>> 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()
>>>
Ответ 3
Класс threading.Timer
имеет метод cancel
, и хотя он не отменяет поток, он остановит таймер от фактического обжига. Фактически происходит то, что метод cancel
устанавливает threading.Event
, и поток, фактически выполняющий threading.Timer
, проверяет это событие после его ожидания и до того, как он действительно выполнит обратный вызов.
Тем не менее, таймеры обычно реализуются без использования отдельного потока для каждого из них. Лучший способ сделать это зависит от того, что делает ваша программа на самом деле (в ожидании этого таймера), но все, что связано с циклом событий, например с графическим интерфейсом и сетевыми инфраструктурами, имеет способы запросить таймер, подключенный к eventloop.
Ответ 4
Вдохновленный вышеупомянутым сообщением.
Отмена и сброс таймера в Python. Он использует поток.
Особенности: запуск, остановка, перезагрузка, функция обратного вызова.
Ввод: время ожидания, значения sleep_chunk и функция обратного вызова.
Может использовать или наследовать этот класс в любой другой программе. Также можно передать аргументы функции обратного вызова.
Таймер также должен отвечать в середине. Не только после завершения полного сна. Поэтому вместо того, чтобы использовать один полный сон, используя небольшие куски сна и продолжая проверять объект события в цикле.
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()