本篇文章给大家带来的内容是关于python实现循环定时器的方法介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
python 如何写一个定时器,循环定时做某一操作呢?
Timer 对象
from threading import Timerdef 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.7def Timer(*args, **kwargs): return _Timer(*args, **kwargs)# python3.7class Timer(Thread): pass
在 python3,Timer 是 Thread 的子类;在 python2,_Timer 是 Thread 的子类,而 Timer 只是 _Timer 类的工厂方法。
上面的代码只会打印一次 hello, world 后退出,那么如何循环间隔打印呢?
粗陋的循环定时器
一种方法是在 function 里继续注册一个 Timer,这样就可以在下一个 interval 继续执行 function;
from threading import Timerdef 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 impor<mark style="color:transparent">本文来源gaodaimacom搞#^代%!码&网*</mark>t _Timerdef 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 Threaddef hello(): print "hello, world"# 继承 Threadclass 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