如何用Python实现任务固定间隔精准调度(非任务结束后计时)
实现schedule库的固定间隔调度(从任务启动时间计时)
默认情况下,schedule库的定时任务采用延迟调度:任务执行完成后才会计算下一次的触发时间,这就导致如果任务执行耗时超过设定间隔,下一次任务会被延后。要实现从任务启动时间开始计时的固定间隔调度,可以通过异步执行任务的方式解决,让调度逻辑不受任务执行阻塞的影响。
解决方案1:使用线程异步执行任务
将任务放到独立线程中运行,这样主调度循环不会被任务执行阻塞,仍能按设定的固定间隔触发下一次任务:
import schedule import time import threading def job(): print("Process triggered at:", time.strftime("%Y-%m-%d %H:%M:%S")) time.sleep(30) print("Process ended at:", time.strftime("%Y-%m-%d %H:%M:%S")) # 包装任务为线程执行 def run_job_async(): threading.Thread(target=job).start() frequency_seconds = 60 # 调度异步任务 schedule.every(frequency_seconds).seconds.do(run_job_async) while True: schedule.run_pending() time.sleep(1)
解决方案2:避免任务重叠(可选)
如果不希望多个任务实例同时运行,可以添加线程锁,让后续任务等待前一个任务完成后再执行,但调度间隔仍保持从启动时间计算:
import schedule import time import threading # 创建线程锁 job_lock = threading.Lock() def job(): with job_lock: print("Process triggered at:", time.strftime("%Y-%m-%d %H:%M:%S")) time.sleep(30) print("Process ended at:", time.strftime("%Y-%m-%d %H:%M:%S")) def run_job_async(): threading.Thread(target=job).start() frequency_seconds = 60 schedule.every(frequency_seconds).seconds.do(run_job_async) while True: schedule.run_pending() time.sleep(1)
效果验证
使用上述代码后,输出会符合预期:
Process triggered at: 2024-03-25 06:57:23
Process ended at: 2024-03-25 06:57:53
Process triggered at: 2024-03-25 06:58:23
Process ended at: 2024-03-25 06:58:53
原理说明
原代码的问题在于单线程执行:任务运行时会阻塞主循环的schedule.run_pending()调用,直到任务结束才会继续检查下一次调度时间。通过线程异步执行任务,主调度循环可以持续按固定间隔触发任务,不受任务执行耗时的影响。
内容的提问来源于stack exchange,提问作者CrazyCoder
相关产品推荐
相关产品推荐

