我们会经常遇到需要定时任务的应用场景。如定时备份数据库,定时发送短信、发布订阅信息等场景。使用Window的任务管理器,Linux的crontab管理定时任务,需要手工来添加,配置工作量多而且无法满足自动化添加定时任务场景。当然可以通过第3方库celery 来实现定时任务管理,但celery使用较复杂,需要额外的开发工作量。
好消息是,python标准库提供了1个内置模块 sched
来管理定时任务,不依赖任何第3方库,而且使用简捷。 sched模块的另一个好处在于它与平台无关,可以在任何操作系统上运行。
import sched
import time
scheduler ``=` `sched.scheduler(time.time, time.sleep)
任务函数包含计划要执行的工作。 如果需要在两个不同的时间需要执行不同的工作,应该将任务拆分为两个任务函数。
使用 sched.enter() 方法来安排任务,执行时间用从当前时间开始向后延迟的秒数来表示。
语法: scheduler.enter(delay, priority, action, argument=(), kwargs={})
参数说明:
启动schedule任务队列,每个任务时间到后,启动该任务函数。 队列中所有任务执行完成后,sched 对象才退出。
enter()方法是根据当前时间向后延迟的秒数来添加任务。但经常我们遇到的场景是,要求在某个时间点来执行任务。
使用方法; sched.enterabs()
Syntax: scheduler.enterabs(time, priority, action, argument=(), kwargs={})
Parameters:
import sched, time
from datetime import datetime, timedelta
s = sched.scheduler(time.time, time.sleep)
def print_time(a: str='default'):
# task function example
print("From print_time", datetime.now(), a)
def calc_gap_second(dt: datetime):
# get gap btw current time and input datetime, unit is second
return dt.timestamp() - datetime.now().timestamp()
def print_some_times():
print(datetime.now())
t1= time.time()
s.enter(10,1, print_time) # 10秒后执行,优先级为1
# 5秒后执行,优先级为2, 输入参数("test-2, )
s.enter(5, 2, print_time, argument=('test_2',))
# 也是5秒后执行,用kwargs方式输入参数
s.enter(5, 2, print_time, kwargs={'a': 'test_3'})
# 预定在某个时间点执行,计算与当前时间的时差
dt1 = datetime.strptime("2023-08-15 16:25:00:000001", "%Y-%m-%d %H:%M:%S:%f")
s1: float = calc_gap_second(dt1)
print("s1:",s1)
# 根据计算好的时差来添加任务。
s.enter(s1, 1, print_time, kwargs={'a': 'test_4'})
# 用enterabs()方法,以时间点来添加任务
s.enterabs(t1+6,1, print_time, kwargs={'a': 'test_5'})
s.run() # 启动监视任务循环
print(time.time)
print_some_times()
output
2023-08-15 16:24:44.827923
s1: 15.162081003189087
From print_time 2023-08-15 16:24:49.830699 test_2
From print_time 2023-08-15 16:24:49.830699 test_3
From print_time 2023-08-15 16:24:50.833527 test_5
From print_time 2023-08-15 16:24:54.829681 default
From print_time 2023-08-15 16:25:00.005648 test_4
查看所有任务
sched.queue 任务队例
取消任务
sched.cancel( event ) 取消单个任务,
event 是enter(), enterabs()添加任务后返回的任务对象。
e1 = scheduler.enter(1, 1, print_event,('1 st', ))
判断任务队列是否为空
shed.empty() 检查queue是否为空,如果是空,返回True.
示例
import sched
import time
scheduler = sched.scheduler(time.time, time.sleep)
def print_event(name):
print('EVENT:', time.time(), name)
print ('START:', time.time())
e1 = scheduler.enter(1, 1, print_event,('1 st', ))
e2 = scheduler.enter(2, 1, print_event,(' 2nd', ))
scheduler.cancel(e1)
print("schedule queue length:", len(s.queue))
scheduler.run()
output:
START: 1580390119.54074
schedule queue length: 1
EVENT: 1580390121.5439944 2nd
高级的定时任务管理库,如 APScheduler ,可以实现更复杂的定时任务管理。