[英]Cancellable threading.Timer in Python
I am trying to write a method that counts down to a given time and unless a restart command is given, it will execute the task.我正在尝试编写一个倒计时到给定时间的方法,除非给出重新启动命令,否则它将执行任务。 But I don't think Python
threading.Timer
class allows for timer to be cancelable.但我不认为 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()
I know the above code is wrong somehow.我知道上面的代码不知何故是错误的。 Would appreciate some kind guidance over here.
很感激这里的一些指导。
You would call the cancel method after you start the timer:您将在启动计时器后调用取消方法:
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()
You might consider using a while-loop on a Thread , instead of using a Timer .您可能会考虑在Thread上使用 while 循环,而不是使用Timer 。
Here is an example appropriated from Nikolaus Gradwohl's answer to another question:以下是 Nikolaus Gradwohl 对另一个问题的回答中的一个示例:
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()
I'm not sure if I understand correctly.我不确定我是否理解正确。 Do you want to write something like in this example?
你想在这个例子中写一些类似的东西吗?
>>> 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()
>>>
The threading.Timer
class does have a cancel
method, and although it won't cancel the thread , it will stop the timer from actually firing. threading.Timer
类确实有一个cancel
方法,虽然它不会取消线程,但它会阻止计时器实际触发。 What actually happens is that the cancel
method sets a threading.Event
, and the thread actually executing the threading.Timer
will check that event after it's done waiting and before it actually executes the callback.实际发生的是
cancel
方法设置了一个threading.Event
,而实际执行threading.Timer
将在完成等待之后和实际执行回调之前检查该事件。
That said, timers are usually implemented without using a separate thread for each one.也就是说,定时器的实现通常不会为每个定时器使用单独的线程。 The best way to do it depends on what your program is actually doing (while waiting for this timer), but anything with an event loop, like GUI and network frameworks, all have ways to request a timer that is hooked into the eventloop.
最好的方法取决于你的程序实际在做什么(在等待这个计时器时),但是任何带有事件循环的东西,比如 GUI 和网络框架,都有方法来请求一个挂接到事件循环中的计时器。
Im not sure if best option but for me is woking like this: t = timer_mgr(.....) append to list "timers.append(t)" and then after all created you can call:我不确定是否最好的选择,但对我来说是这样的: t = timer_mgr(.....) append to list "timers.append(t)" 然后在创建之后你可以调用:
for tm in timers:#threading.enumerate():
print "********", tm.cancel()
my timer_mgr() class is this:我的 timer_mgr() 类是这样的:
class timer_mgr():
def __init__(self, st, t, hFunction, id, name):
self.is_list = (type(st) is list)
self.st = st
self.t = t
self.id = id
self.hFunction = hFunction
self.thread = threading.Timer(t, self.handle_function, [id])
self.thread.name = name
def handle_function(self, id):
if self.is_list:
print "run_at_time:", datetime.now()
self.hFunction(id)
dt = schedule_fixed_times(datetime.now(), self.st)
print "next:", dt
self.t = (dt-datetime.now()).total_seconds()
else:
self.t = self.st
print "run_every", self.t, datetime.now()
self.hFunction(id)
self.thread = threading.Timer(self.t, self.handle_function, [id])
self.thread.start()
def start(self):
self.thread.start()
def cancel(self):
self.thread.cancel()
Inspired by above post.灵感来自上面的帖子。 Cancelable and Resetting Timer in Python.
Python 中的可取消和重置计时器。 It uses thread.
它使用线程。
Features: Start, Stop, Restart, callback function.功能:启动、停止、重启、回调函数。
Input: Timeout, sleep_chunk values, and callback_function.输入:超时、sleep_chunk 值和 callback_function。
Can use or inherit this class in any other program.可以在任何其他程序中使用或继承此类。 Can also pass arguments to the callback function.
也可以将参数传递给回调函数。
Timer should respond in middle also.定时器也应该在中间响应。 Not just after completion of full sleep time.
不仅仅是在完成完整的睡眠时间之后。 So instead of using one full sleep, using small chunks of sleep and kept checking event object in loop.
因此,与其使用一个完整的睡眠,不如使用一小块睡眠并在循环中不断检查事件对象。
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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.