python 怎样写一个定时器,轮回定时做某一操纵呢?
Timer 对象
from threading import Timer def hello(): print "hello, world" t = Timer(10.0, hello) t.start()
10秒后输出:
hello, world
重点研讨 t = Timer(10.0, hello) 这句代码,python 供应了一个Timer 对象,它会在指定的时刻后实行某一操纵;它的完全情势:
class threading.Timer(interval, function, args=[], kwargs={})
interval 是时刻距离,function 是可挪用的对象,args 和 kwargs 会作为 function 的参数。
注重:这里只会实行一次 function,而不会一向定时实行,且 Timer 在实行操纵的时刻会建立一个新的线程。
Timer 在 python2 和 python3 有点区分:
# python2.7 def Timer(*args, **kwargs): return _Timer(*args, **kwargs) # python3.7 class Timer(Thread): pass
在 python3,Timer 是 Thread 的子类;在 python2,_Timer 是 Thread 的子类,而 Timer 只是 _Timer 类的工场要领。
上面的代码只会打印一次 hello, world 后退出,那末怎样轮回距离打印呢?
粗陋的轮回定时器
一种要领是在 function 里继续注册一个 Timer,如许就能够鄙人一个 interval 继续实行 function;
from threading import Timer def hello(): print "hello, world" Timer(10.0, hello) .start() t = Timer(10.0, hello) t.start()
每隔 10 秒输出一个 hello, world。
抵达结果了,然则这内里彷佛有点题目。回到 Timer 自身,它是一个 thread,每次轮回距离操纵,体系都要建立一个线程,然后再接纳,这对体系来讲开支很大。假如时刻距离 interval 很短,体系会一会儿建立许多线程,这些线程很难疾速接纳,致使体系内存和cpu资本被消耗掉。
所以不首倡在 function 里继续注册一个 Timer。
更 pythonic 轮回定时器
这里有更 pythonic 的要领:
from threading import _Timer def hello(): print "hello, world" class RepeatingTimer(_Timer): def run(self): while not self.finished.is_set(): self.function(*self.args, **self.kwargs) self.finished.wait(self.interval) t = RepeatingTimer(10.0, hello) t.start()
重点研讨 RepeatingTimer 类,它继续了 threading._Timer,然则重写了父类的 run 要领。这是 Python2 的写法,python3 中 RepeatingTimer 应当继续 threading.Timer。
为何要重写 Thread 的 run 要领?
_Timer 是一个 Thread 子类,我们先看看 Thread 类的 run 用法。
from threading import Thread def hello(): print "hello, world" # 继续 Thread class MyThread(Thread): # 把要实行的代码写到run函数内里 线程在建立后会直接运转run函数 def run(self): hello() t = MyThread() t.start()
Thread 对象的完全定义:
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
个中 run 要领代码:
class Thread(_Verbose): def run(self): try: if self.__target: self.__target(*self.__args, **self.__kwargs) finally: # Avoid a refcycle if the thread is running a function with # an argument that has a member that points to the thread. del self.__target, self.__args, self.__kwargs
规范的 run 要领用于实行用户传入组织函数的 target 要领。 子类能够重写 run 要领,把要实行的代码写到 run 内里,线程在建立后,用户挪用 start() 要领会运转 run() 要领。
所以 RepeatingTimer 重写 _Timer 的 run() 要领,能够转变线程的实行体,当我们挪用 RepeatingTimer 的 start() 要领时会实行我们重写的 run() 要领。
再看看 RepeatingTimer 类中的 while not self.finished.is_set() 语句,self.finished.is_set() 直到 True 才会退出轮回,定时器才完毕。finished 是 threading.Event 对象。一个 Event 对象治理着一个 flag 标志,它能被 set() 要领设置为 True,也能被 clear() 要领设置为 False,挪用 wait([timeout]) 线程会一向 sleep 到 flag 为 True 或超时时刻抵达。
我们晓得定时器有一个 cancel() 要领能够提早作废操纵。它实际上是挪用 Event.clear() 要领提早让 wait 要领完毕守候,而且推断在 flag 为 true 的状况下不实行定时器操纵。细致的代码:
class _Timer(Thread): """Call a function after a specified number of seconds: t = Timer(30.0, f, args=[], kwargs={}) t.start() t.cancel() # stop the timer's action if it's still waiting """ def __init__(self, interval, function, args=[], kwargs={}): Thread.__init__(self) self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.finished = Event() def cancel(self): """Stop the timer if it hasn't finished yet""" self.finished.set() def run(self): self.finished.wait(self.interval) if not self.finished.is_set(): self.function(*self.args, **self.kwargs) self.finished.set()
所以 RepeatingTimer 的 run 要领会一向实行 while 轮回体,在轮回体了会实行用户传入的 function 对象,并守候指定的时刻。当用户想退出定时器时,只须要挪用 cancel 要领,将 flag 置为 True 便不会继续实行轮回体了。如许便完成了一个还不错的轮回定时器。
以上就是python完成轮回定时器的要领引见(附代码)的细致内容,更多请关注ki4网别的相干文章!