You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

APScheduler定时任务重复执行求助:周五8:05触发却执行两次

问题:APScheduler定时任务重复执行的原因?

我配置了一个APScheduler定时任务,期望每周五上午8:05执行,并设置了15分钟的jitter(抖动)。代码如下:

from apscheduler.schedulers.background import BackgroundScheduler
import requests
import time  # 补充缺失的导入

sched = BackgroundScheduler()

def WOL():
    requests.get("https://example.com/WOL")

sched.add_job(WOL, 'cron', hour=8, minute=5, jitter=900, day_of_week='fri')
sched.start()

try:
    while True:
        time.sleep(2)
except (KeyboardInterrupt, SystemExit):
    sched.shutdown()

但任务实际执行了两次,当日运行日志如下:

2024-01-05 08:04:17,657 - INFO - Running job "WOL (trigger: cron[day_of_week='fri', hour='8', minute='5'], next run at: 2024-01-05 08:13:47 PST)" (scheduled at 2024-01-05 08:04:17.646354-08:00)
2024-01-05 08:04:19,848 - INFO - Job "WOL (trigger: cron[day_of_week='fri', hour='8', minute='5'], next run at: 2024-01-05 08:13:47 PST)" executed successfully
2024-01-05 08:13:47,596 - INFO - Running job "WOL (trigger: cron[day_of_week='fri', hour='8', minute='5'], next run at: 2024-01-12 08:12:15 PST)" (scheduled at 2024-01-05 08:13:47.591469-08:00)
2024-01-05 08:13:49,608 - INFO - Job "WOL (trigger: cron[day_of_week='fri', hour='8', minute='5'], next run at: 2024-01-12 08:12:15 PST)" executed successfully

任务分别在8:04和8:13执行了,请问调度配置哪里出了问题?


原因与解决方案

问题原因

当在cron触发器中搭配jitter参数时,如果调度器启动时间早于cron指定的目标时间(比如周五8:00启动,目标时间为8:05),调度器会错误生成两次运行计划:

  1. 第一次以启动时间为基准添加随机抖动,导致任务在目标时间前提前执行;
  2. 第二次以cron目标时间为基准添加随机抖动,属于符合预期的周五8:05±15分钟窗口内执行。

这是因为APScheduler默认会基于当前启动时间计算首次运行的抖动时间,忽略了cron表达式的固定时间约束。

解决方案

通过指定start_date参数,强制首次运行时间不早于cron目标时间(周五8:05),让调度器仅生成符合预期的单次周度计划:

from apscheduler.schedulers.background import BackgroundScheduler
import requests
import time
from datetime import datetime, timedelta

sched = BackgroundScheduler()

def WOL():
    requests.get("https://example.com/WOL")

# 计算首个符合要求的周五8:05时间点
now = datetime.now()
# weekday()返回0=周一,4=周五,计算距离下一个周五的天数
days_to_friday = (4 - now.weekday() + 7) % 7
next_friday = now + timedelta(days=days_to_friday)
next_friday = next_friday.replace(hour=8, minute=5, second=0, microsecond=0)
# 如果当前时间已过本周周五8:05,自动顺延至下周
if now >= next_friday:
    next_friday += timedelta(weeks=1)

# 添加任务时指定start_date约束首次运行时间
sched.add_job(WOL, 'cron', hour=8, minute=5, jitter=900, day_of_week='fri', start_date=next_friday)
sched.start()

try:
    while True:
        time.sleep(2)
except (KeyboardInterrupt, SystemExit):
    sched.shutdown()

额外注意事项

  1. 补充代码中缺失的import requests和import time,避免运行报错;
  2. 确保调度器进程仅启动一次,防止重复添加任务导致多次执行;
  3. 若无需处理错过的任务,可设置misfire_grace_time=0,但不推荐用于需保证执行的定时任务。

内容的提问来源于stack exchange,提问作者Bijan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:40:55