schedule定时任务10种写法:从每5秒到每周三,一次学会所有周期调度
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 中查看每个方法的行为定义。