python从写循环定时器学习Timer
python 如何写⼀个定时器,循环定时做某⼀操作呢?
Timer 对象
from threading import Timer
def hello():
print "hello, world"
t = Timer(10.0, hello)
t.start()
复制代码
10秒后输出:
hello, world
kelly ripa
复制代码
重点研究 t = Timer(10.0, hello) 这句代码,python 提供了⼀个,它会在指定的时间后执⾏某⼀操作;它的完整形式:
湿漉漉class threading.Timer(interval, function, args=[], kwargs={})
复制代码
interval 是时间间隔,function 是可调⽤的对象,args 和 kwargs 会作为 function 的参数。
注意:这⾥只会执⾏⼀次 function,⽽不会⼀直定时执⾏,且 Timer 在执⾏操作的时候会创建⼀个新的线程。
default gatewayTimer 在 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(lf):
while not lf.finished.is_t():
lf.function(*lf.args, **lf.kwargs)
lf.finished.wait(lf.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(lf):
hello()
t = MyThread()
t.start()
viagra是什么意思
复制代码
Thread 对象的完整定义:千玺出席青年论坛
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
复制代码
wpa
其中 run ⽅法代码:
class Thread(_Verbo):
def run(lf):
好主意的英文try:
if lf.__target:
lf.__target(*lf.__args, **lf.__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 lf.__target, lf.__args, lf.__kwargs
复制代码
标准的 run ⽅法⽤于执⾏⽤户传⼊构造函数的 target ⽅法。 ⼦类可以重写 run ⽅法,把要执⾏的代码写到 run ⾥⾯,线程在创建后,⽤户调⽤ start() ⽅法会运⾏ run() ⽅法。
所以 RepeatingTimer 重写 _Timer 的 run() ⽅法,可以改变线程的执⾏体,当我们调⽤ RepeatingTimer 的 start() ⽅法时会执⾏我们重写的 run() ⽅法。
再看看 RepeatingTimer 类中的 while not lf.finished.is_t() 语句,lf.finished.is_t() 直到 True 才会退出循环,定时器才结
束。finished 是 threading.Event 对象。⼀个 Event 对象管理着⼀个 flag 标志,它能被 t() ⽅法设置为 True,也能被 clear() ⽅法设置为Fal,调⽤ wait([timeout]) 线程会⼀直 sleep 到 flag 为 True 或超时时间到达。
我们知道定时器有⼀个 cancel() ⽅法可以提前取消操作。它其实是调⽤ Event.clear() ⽅法提前让 wait ⽅法结束等待,并且判断在 flag 为true 的情况下不执⾏定时器操作。具体的代码:
class _Timer(Thread):
"""Call a function after a specified number of conds:
t = Timer(30.0, f, args=[], kwargs={})
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
def __init__(lf, interval, function, args=[], kwargs={}):
Thread.__init__(lf)
lf.interval = interval
lf.function = function
lf.args = args
lf.kwargs = kwargs
lf.finished = Event()
def cancel(lf):
also怎么读
"""Stop the timer if it hasn't finished yet"""
lf.finished.t()
def run(lf):
lna是哪个国家的缩写lf.finished.wait(lf.interval)
if not lf.finished.is_t():
lf.function(*lf.args, **lf.kwargs)
lf.finished.t()
复制代码
所以 RepeatingTimer 的 run ⽅法会⼀直执⾏ while 循环体,在循环体了会执⾏⽤户传⼊的 function 对象,并等待指定的时间。当⽤户想退出定时器时,只需要调⽤ cancel ⽅法,将 flag 置为 True 便不会继续执⾏循环体了。这样便完成了⼀个还不错的循环定时器。