python中的轻量级定时任务调度库:schedule
Posted 一蓑烟雨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python中的轻量级定时任务调度库:schedule相关的知识,希望对你有一定的参考价值。
提到定时任务调度的时候,相信很多人会想到celery,要么就写个脚本塞到crontab中。不过,一个小的定时脚本,要用celery的话太“重”了。所以,我找到了一个轻量级的定时任务调度的库:schedule。
任务调度,轻量级的定时任务调度的库:schedule。
库的安装还是最简单的pip install schedule,使用起来也是很容易理解的。
1 import schedule 2 import time 3 4 def job(): 5 print("I‘m working...") 6 7 schedule.every(10).minutes.do(job) 8 schedule.every().hour.do(job) 9 schedule.every().day.at("10:30").do(job) 10 schedule.every(5).to(10).days.do(job) 11 schedule.every().monday.do(job) 12 schedule.every().wednesday.at("13:15").do(job) 13 14 while True: 15 schedule.run_pending() 16 time.sleep(1)
这是在pypi上面给出的示例。这个栗子简单到我不需要怎么解释。而且,通过这个栗子,我们也可以知道,schedule其实就只是个定时器。在while True死循环中,schedule.run_pending()是保持schedule一直运行,去查询上面那一堆的任务,在任务中,就可以设置不同的时间去运行。跟crontab是类似的。
但是,如果是多个任务运行的话,实际上它们是按照顺序从上往下挨个执行的。如果上面的任务比较复杂,会影响到下面任务的运行时间。比如我们这样:
1 import datetime 2 import schedule 3 import time 4 5 def job1(): 6 print("I‘m working for job1") 7 time.sleep(2) 8 print("job1:", datetime.datetime.now()) 9 10 def job2(): 11 print("I‘m working for job2") 12 time.sleep(2) 13 print("job2:", datetime.datetime.now()) 14 15 def run(): 16 schedule.every(10).seconds.do(job1) 17 schedule.every(10).seconds.do(job2) 18 19 while True: 20 schedule.run_pending() 21 time.sleep(1)
接下来你就会发现,两个定时任务并不是10秒运行一次,而是12秒。是的。由于job1和job2本身的执行时间,导致任务延迟了。
其实解决方法也很简单:用多线程/多进程。不要幼稚地问我“python中的多线程不是没有用吗?”这是两码事。开了一条线程,就把job独立出去运行了,不会占主进程的cpu时间,schedule并没有花掉执行一个任务的时间,它的开销只是开启一条线程的时间,所以,下一次执行就变成了10秒后而不是12秒后。
1 import datetime 2 import schedule 3 import threading 4 import time 5 6 def job1(): 7 print("I‘m working for job1") 8 time.sleep(2) 9 print("job1:", datetime.datetime.now()) 10 11 def job2(): 12 print("I‘m working for job2") 13 time.sleep(2) 14 print("job2:", datetime.datetime.now()) 15 16 def job1_task(): 17 threading.Thread(target=job1).start() 18 19 def job2_task(): 20 threading.Thread(target=job2).start() 21 22 def run(): 23 schedule.every(10).seconds.do(job1_task) 24 schedule.every(10).seconds.do(job2_task) 25 26 while True: 27 schedule.run_pending() 28 time.sleep(1)
就是这么简单。
唯一要注意的是,这里面job不应当是死循环类型的,也就是说,这个线程应该有一个执行完毕的出口。一是因为线程万一僵死,会是非常棘手的问题;二是下一次定时任务还会开启一个新的线程,执行次数多了就会演变成灾难。如果schedule的时间间隔设置得比job执行的时间短,一样会线程堆积形成灾难,所以,还是需要注意一下的。
schedule这个库使用起来比较简单,内容不是很多。我这里介绍的大概用法基本上够用了,还想了解其他特性的话,可以参考官网:https://schedule.readthedocs.io/en/stable/
例子:
1 import datetime 2 import schedule 3 import time 4 5 def job1(): 6 print("I‘m working for job1") 7 time.sleep(2) 8 print("job1:", datetime.datetime.now()) 9 10 def job2(): 11 print("I‘m working for job2") 12 time.sleep(2) 13 print("job2:", datetime.datetime.now()) 14 15 def run(): 16 schedule.every().day.at("22:19").do(job1) 17 schedule.every().day.at("22:19").do(job2) 18 #schedule.every(3).seconds.do(job1) 19 #schedule.every(3).seconds.do(job2) 20 21 while True: 22 schedule.run_pending() 23 time.sleep(1) 24 25 26 if __name__ == "__main__": 27 28 run()
多线程例子
1 import datetime 2 import schedule 3 import threading 4 import time 5 6 def job1(): 7 print("I‘m working for job1") 8 time.sleep(2) 9 print("job1:", datetime.datetime.now()) 10 11 def job2(): 12 print("I‘m working for job2") 13 time.sleep(2) 14 print("job2:", datetime.datetime.now()) 15 16 def job1_task(): 17 threading.Thread(target=job1).start() 18 19 def job2_task(): 20 threading.Thread(target=job2).start() 21 22 23 def run(): 24 schedule.every().day.at("22:23").do(job1_task) 25 schedule.every().day.at("22:23").do(job2_task) 26 #schedule.every(3).seconds.do(job1_task) 27 #schedule.every(3).seconds.do(job2_task) 28 29 while True: 30 schedule.run_pending() 31 time.sleep(1) 32 33 34 if __name__ == "__main__": 35 36 run() 37
以上是关于python中的轻量级定时任务调度库:schedule的主要内容,如果未能解决你的问题,请参考以下文章