背景
当我们在写业务逻辑时,常常会用到一些定时触发的任务,比如定时清理、定时补偿、定时报警、定时同步、定时发送等等等。这些任务一般是轻量级的,因此使用一个线程去处理即可。
介绍两种实现方式,方式一是使用python内建模块sched,方式二是使用第三方模块schedule。
内建sched模块
sched模块实现了一个通用事件调度器,在调度器类使用一个延迟函数等待特定的时间,执行指定的任务(函数)。同时支持多线程应用程序,在每个任务执行后会立刻调用延时函数,以确保其他线程也能执行。
step1:生成调度器
scheduler_handler = sched.scheduler(time.time, time.sleep)
step2:自定义任务
def task_function():
#=========================
# TODO: 你的业务逻辑代码
#=========================
scheduler_handler.enter(timer_interval, 0, task_function, (arg,))
timer_interval:定时任务的触发的时间间隔
step3:注册任务
scheduler_handler.enter(delay_seconds, 0, task_function, (arg,))
enter()方法,包含4个参数:
-
触发任务的延迟时间(单位为秒),如果为0,当执行run()方法后会立即执行。
-
优先级(多个事件在同一时间触发的情况下,优先级高的优先执行)
-
任务函数
-
任务函数的传入参数
step4:开启调度器
scheduler_handler.run()
调用run()方法后,调度器开始计时,到达指定时间后会执行对应的事件。每个事件都在同一线程中运行,所以如果一个事件需要更长的时间,延迟事件将会有重叠。为了防止丢失事件,延迟事件将会在之前事件运行完再被执行,但一些延迟事件可能会晚于原本计划的事件。
第三方模块schedule
step1:自定义任务
def task_function():
#=========================
# TODO: 你的业务逻辑代码
#=========================
step2:注册任务
# 每隔10分钟触发一次任务
schedule.every(10).minutes.do(task_function, arg)
# 每隔一小时触发一次任务(every函数无入参时使用默认参数:1)
schedule.every().hour.do(task_function, arg)
# 每天的10:30触发一次任务
schedule.every().day.at("23:30").do(task_function, arg)
# 每隔3到7天触发一次任务
schedule.every(3).to(7).days.do(task_function, arg)
# 每周一的这个时间点触发一次任务
schedule.every().monday.do(task_function, arg)
# 每周六的20:00触发一次任务
schedule.every().saturday.at("20:00").do(task_function, arg)
step3:开启调度器
while True:
schedule.run_pending()
time.sleep(seconds) # 此处的睡眠时间很关键
run_pending()方法每执行一次,调度器会检查一次任务是否到达指定时间,已经到达时间的任务就会触发。因此需要循环调用run_pending()。循环中的睡眠时间决定了调度器的检查时间间隔,因此当任务精度为秒时,睡眠时间建议为1秒,,当任务精度为分时,睡眠时间建议为1分,以此类推。