在工作中,我们时常会碰到需要周期性执行的任务。这里特地对自动化实现定时任务的方式做了归纳整理。特此说明,该篇文章只整理了定时任务的python实现方式。
1. 利用while True + time.sleep()实现定时任务
time模块中的sleep(secs)函数,可以使得当前的线程暂停等待secs秒之后再继续执行。简而言之,就是当前的线程进入阻塞状态,等待secs秒之后,再由等待状态变为就绪状态,等待系CPU进行调度
基于该函数的特点,我们可以通过while True + time.sleep()的方式实现简单的定时任务
具体代码如下:
import time
import datetime
def task_func():
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
print('这是一个输出打印字符的定时任务')
print('*******')
def loop_monitor():
while True:
task_func()
time.sleep(5)
if __name__ == '__main__':
loop_monitor()
result:
这个定时任务是每隔5秒钟打印出7个*,并且打印出当前时间。
这种实现方式虽然简单高效,但是有其不足之处。主要缺点如下:
(1) 只能设置时间间隔,不能指定具体时间,比如每天21:00这种的就不行
(2) 这种方式是一个阻塞函数,也就是说sleep的这段时间内,程序啥也干不了。只能乖乖的等待
2. 利用threading.Timer实现定时任务
threading模块中的Timer是一个非阻塞函数,比sleep稍微好一点。timer最基本的理解就是定时器,我们可以启动多个定时任务,这些定时器任务是异步执行,所以不存在等待执行顺序问题。
具体用法如下:
Timer(interval, function, args=[], kwargs={})
interval: 指定的时间
function: 要执行的方法
args/kwargs:要执行的方法的参数
具体代码如下:
import datetime
from threading import Timer
def time_printer():
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print(f'this time {ts}')
loop_monitor()
def loop_monitor():
t = Timer(5, time_printer)
t.start()
if __name__ == '__main__':
loop_monitor()
result:
3. 利用内置模块sched实现定时任务
sched模块实现了一个通用事件调度器,在调度器类使用了一个延迟函数等待特定的时间,执行任务。同时支持多线程应用程序,在每个任务执行后会立刻调用延时函数,以确保其他线程也能执行。
sched.scheduler(timefunc, delayfunc)这个类定义了调度事件的通用接口,他需要外部传入两个参数。timefunc是一个没有参数的返回时间类型数字的函数(经常使用time.time()),delayfunc是一个需要参数调用、与timefunc的输出兼容、作用为延迟多个时间单位的函数(常用的比如time.sleep())
具体代码如下:
import datetime
import time
import sched
def time_printer():
now = datetime.datetime.now()
ts = now.strftime('%Y-%m-%d %H:%M:%S')
print(f'this time is {ts}')
loop_monitor()
def loop_monitor():
t = sched.scheduler(time.time, time.sleep)
t.enter(5, 1, time_printer, ())
t.run()
if __name__ == '__main__':
loop_monitor()
result:
scheduler对象主要方法:
enter(delay, priority, action, argument):安排一个时间来延迟delay个时间单位
cancel(event): 从队列中删除事件。如果事件不是当前队列中的事件,则该方法将跑出一个ValueError
run():运行所有预定的事件。这个函数先等待,然后执行事件,直到不再有预定的事件
4.利用APScheduler框架实现
APScheduler是定时任务框架,提供了基于日期、固定时间间隔以及crontab类型的任务,并且可以持久化任务。它主要有以下几个特点: (1) 类似于Linux/Cron的调度程序(可以选择开始和结束时间)
(2) 基于时间间隔的执行调度(周期性调度,可以选择开始和结束时间)
(3) 一次性执行任务(在设定的日期/时间运行一次任务)
具体代码如下:
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
def task_job():
print(f'定时任务在执行{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}')
if __name__ == '__main__':
sched = BlockingScheduler()
sched.add_job(task_job, 'interval', seconds=5, id='my_job_id')
sched.start()
result:
该框架可以指定具体时刻执行
sched.add_job(task_job, 'cron', month='10-12', day='3rd', hour='0-3')
意思是每年的10月3号和12月3号早上0点到3点执行该任务