schedule定时任务10种写法:从每5秒到每周三,一次学会所有周期调度

原创2026-09-21 23:55:171,702 阅读
文章标签:任务调度后端

schedule定时任务10种写法:从每5秒到每周三,一次学会所有周期调度

如果你正在寻找一款好用的 Python 定时任务调度库,schedule 就是那个"为人类而设计"的轻量级定时任务工具。一行 pip install schedule 即可安装,零外部依赖,用接近自然语言的写法(如 every().day.at("10:30"))就能搞定从每 5 秒到每周三的绝大多数周期调度需求。下面一次性讲清 10 种定时任务写法,看完即可上手。

安装 schedule:一条命令搞定

安装非常简单,推荐使用 pip(支持 Python 3.7~3.8 及以上版本):

$ pip install schedule

💡 唯一可选依赖:使用带时区的 .at() 写法时需要安装 pytz。安装方式详见 docs/installation.rst。

核心源码仅一个文件 schedule/init.py,非常易读,想深入了解实现原理可直接翻阅源码。

写法 1:固定间隔调度——每 N 秒/分钟/小时/天/周

最常用的写法,every(N).单位 表示"从当前时刻起,每 N 个单位执行一次":

schedule.every(5).seconds.do(job)      # 每 5 秒
schedule.every(10).minutes.do(job)     # 每 10 分钟
schedule.every(3).days.do(job)         # 每 3 天
schedule.every(2).weeks.do(job)        # 每 2 周

单位可以是 seconds、minutes、hours、days、weeks,改数字即可切换频率,源码实现见 schedule/init.py。

写法 2:随机间隔调度——防止请求过于规律

.to() 让任务在 [A, B] 区间内随机取值,适合模拟人工操作、抓取等场景:

schedule.every(5).to(10).seconds.do(job)   # 每 5~10 秒(随机)执行一次

写法 3:整点内的精确分钟/秒

用 :MM 或 :SS 指定"每小时的第几分钟"、"每分钟的哪一秒":

schedule.every().hour.at(":42").do(job)    # 每小时第 42 分钟执行
schedule.every().minute.at(":17").do(job)  # 每分钟第 17 秒执行

⏰ 注意区分:hour 配 :MM 是分钟,minute 配 :SS 是秒,schedule 会根据时间单位自动推断,无需担心。

写法 4:每天固定时刻执行

最经典的"每天 10:30 跑一次":

schedule.every().day.at("10:30").do(job)
schedule.every().day.at("10:30:42").do(job)   # 精确到秒

时间格式为 HH:MM 或 HH:MM:SS,格式校验逻辑见 schedule/init.py。

写法 5:每 N 小时在指定时刻触发

every(5).hours.at("20:30") 表示"每隔 5 小时,并在第 20 小时 30 分执行"。若当前是 02:00,则首次执行时间为 06:20:30:

schedule.every(5).hours.at("20:30").do(job)

写法 6:每周固定某一天

直接写星期几,无需任何 cron 表达式:

schedule.every().monday.do(job)            # 每周一
schedule.every().saturday.at("09:00").do(job)  # 每周六早上 9 点

写法 7:每周三固定时刻

给星期任务加上 .at(),就是"每周三 13:15 执行":

schedule.every().wednesday.at("13:15").do(job)

这是很多报表、邮件推送场景的标准写法,完整示例参考 docs/examples.rst。

写法 8:跨时区定时任务

在 .at() 中传入时区字符串即可,适合服务器不在目标时区的情况:

schedule.every().day.at("12:42", "Europe/Amsterdam").do(job)

时区相关细节(含夏令时处理)见 docs/timezones.rst。

写法 9:装饰器方式注册定时任务

不想手动调用 .do()?用 @repeat 装饰器更优雅:

from schedule import every, repeat, run_pending

@repeat(every(10).minutes)
def job():
    print("I am a scheduled job")

一个函数甚至可以叠加多个 @repeat,同时按秒和按天各跑一次。装饰器实现见 schedule/init.py。

写法 10:给任务传参

.do() 后面的参数会原样透传给任务函数,支持位置参数和关键字参数:

def greet(name):
    print('Hello', name)

schedule.every(2).seconds.do(greet, name='Alice')

让任务真正跑起来:run_pending 主循环

注册任务后,需要在一个循环里反复调用 run_pending() 来驱动调度:

import schedule, time

while True:
    schedule.run_pending()
    time.sleep(1)

📌 两个实用技巧:

  • 精确休眠:用 schedule.idle_seconds() 获取距下一次执行的秒数,替代固定 time.sleep(1),实现见 schedule/init.py;
  • 立即执行所有任务:调试时用 schedule.run_all(delay_seconds=10) 忽略调度时间立即执行全部任务。

进阶:让定时任务更好用的 4 个技巧

1️⃣ 设定任务截止时间(until)

schedule.every(1).hours.until("18:30").do(job)   # 只在今天 18:30 前执行
schedule.every(1).hours.until(timedelta(hours=8)).do(job)  # 只跑 8 小时

2️⃣ 一次性任务(只执行一次)

任务函数返回 schedule.CancelJob 后,任务会自动从调度器中移除:

def job_once():
    # ...一次性工作...
    return schedule.CancelJob

3️⃣ 后台线程运行,不阻塞主程序

官方文档提供了一份现成的线程方案,参考 docs/background-execution.rst,适合 GUI 或 Web 应用集成。

4️⃣ 任务分组管理:标签与批量取消

schedule.every().day.do(greet, 'Andrea').tag('daily-tasks', 'friend')
schedule.clear('daily-tasks')   # 一键取消所有带该标签的任务

总结:一张表回顾 10 种写法

# 写法 含义
1 every(5).seconds 固定间隔(秒/分/时/天/周通用)
2 every(5).to(10).seconds 5~10 秒随机间隔
3 every().hour.at(":42") 每小时第 42 分钟
4 every().day.at("10:30") 每天固定时刻
5 every(5).hours.at("20:30") 每 5 小时 + 固定时刻
6 every().monday 每周固定某天
7 every().wednesday.at("13:15") 每周三 13:15
8 every().day.at("12:42", "Europe/Amsterdam") 跨时区任务
9 @repeat(every(10).minutes) 装饰器注册
10 do(job, name='Alice') 任务传参

schedule 主打"简单、轻量、无依赖",绝大多数 Python 定时任务、周期调度场景都能覆盖。想继续深入,可以看看官方示例集 docs/examples.rst、常见问题 docs/faq.rst,或者直接在源码 schedule/init.py 中查看每个方法的行为定义。

登录后查看全文
schedule