当前位置:首页 > 文章列表 > 文章 > python教程 > Python sched 定时任务小实验:注册任务、轮询运行和失败重试

Python sched 定时任务小实验:注册任务、轮询运行和失败重试

来源:17golang原创 2026-06-29 10:19:36 0浏览 收藏

有些本地自动化脚本不需要 Celery、APScheduler 或系统级计划任务。比如每隔几秒刷新一次状态、延迟几秒再处理一个文件、在小工具里排几个一次性动作,这类场景用 Python 标准库 sched 就能完成。

本文按“后端实验室”的方式做一个小实验:先注册几个定时任务,再用轮询循环驱动调度器,随后加入周期任务和失败重试,最后用输出结果确认它是否按预期工作。

目录
  • 前置条件:sched 适合什么场景
  • 初始化:准备任务函数和 sched 调度器
  • 编写代码:一次性任务和轮询循环
  • 运行检查:确认顺序、延迟和输出
  • 扩展实验:给失败任务加一次重试
  • 清理总结:哪些边界不要忽略

前置条件:sched 适合什么场景

sched 是 Python 标准库里的轻量调度器。它负责按时间顺序保存任务,到点后调用对应函数。它不自带持久化、不负责跨进程协调,也不适合承载大量线上任务。

适合使用它的场景通常有三个特点:

  • 任务数量少,运行在单个 Python 进程里。
  • 任务可以接受秒级延迟,不要求毫秒级精度。
  • 重启后任务丢失可以接受,或者任务可由上层逻辑重新注册。

本实验只需要 Python 3、终端和一个空目录。代码只使用标准库,不需要额外安装依赖。

初始化:准备任务函数和 sched 调度器

先准备一个最小版本:两个任务分别在 1 秒和 3 秒后运行。sched.scheduler 需要两个函数:一个用来获取当前时间,一个用来等待。这里用 time.monotonictime.sleep,避免系统时间调整影响相对延迟。

Python sched 从注册任务、计算时间、进入队列到输出结果的流程图

import sched
import time

timer = sched.scheduler(time.monotonic, time.sleep)


def log_line(name: str) -> None:
    now = time.strftime("%H:%M:%S")
    print(f"[{now}] {name}")


timer.enter(delay=1, priority=1, action=log_line, argument=("task A",))
timer.enter(delay=3, priority=1, action=log_line, argument=("task B",))

timer.run()

delay 表示从当前时间往后推多少秒,priority 用来处理同一时刻的多个任务,数字越小越先运行。action 是到点后调用的函数,argument 是传给函数的位置参数。

编写代码:一次性任务和轮询循环

直接调用 timer.run() 会阻塞到队列清空。很多本地工具还要同时处理键盘输入、文件扫描或网络轮询,所以更常见的方式是用 blocking=False 做非阻塞检查。

import sched
import time

timer = sched.scheduler(time.monotonic, time.sleep)


def log_line(name: str) -> None:
    now = time.strftime("%H:%M:%S")
    print(f"[{now}] {name}")


def add_once(delay: int, name: str) -> None:
    timer.enter(delay, 1, log_line, argument=(name,))


def run_loop(seconds: int) -> None:
    end_at = time.monotonic() + seconds
    while time.monotonic() 

这段代码的关键是固定轮询间隔。timer.run(blocking=False) 只会运行已经到点的任务,不会在下一个任务前一直等待;循环里的 sleep(0.2) 用来避免 CPU 空转。

加入周期任务

sched 没有内置 cron 表达式,但可以在任务函数末尾重新注册自己,从而形成周期任务。

def every(seconds: int, name: str) -> None:
    def job() -> None:
        log_line(name)
        timer.enter(seconds, 1, job)

    timer.enter(seconds, 1, job)


every(2, "heartbeat")
run_loop(7)

这种写法的优点是简单直观,缺点也要明确:如果任务本身运行很久,下一次注册时间会被推迟。对于本地脚本这通常可以接受;如果要严格固定时间点,就需要更完整的调度框架。

运行检查:确认顺序、延迟和输出

先保存为 mini_timer.py,再运行:

python mini_timer.py

你应该能看到类似输出:

[10:12:01] check config
[10:12:02] refresh cache
[10:12:04] write report

检查时关注三点:

  • 顺序是否和 delay 一致。
  • 程序是否在任务队列清空后退出。
  • 轮询间隔是否过小导致 CPU 占用异常。

如果输出顺序不符合预期,先看注册任务时的 delaypriority。如果程序迟迟不退出,通常是周期任务一直重新注册,需要给循环设置结束条件。

扩展实验:给失败任务加一次重试

定时任务最容易被忽略的是失败边界。下面模拟一个任务第一次失败,3 秒后重试一次,第二次成功。

Python sched 任务失败后记录次数、延迟重试、再次运行并验收通过的流程图

attempts = {"sync_report": 0}


def sync_report() -> None:
    attempts["sync_report"] += 1
    count = attempts["sync_report"]

    if count == 1:
        print("[warn] sync_report failed, retry after 3s")
        timer.enter(3, 1, sync_report)
        return

    print("[ok] sync_report finished")


timer.enter(1, 1, sync_report)
run_loop(6)

预期输出如下:

[warn] sync_report failed, retry after 3s
[ok] sync_report finished

真实项目里不要无限重试。可以给任务记录最大次数,例如最多 3 次;超过次数后打印错误日志,或者把任务写入待人工处理的文件。这样脚本不会因为一个坏任务一直占用运行时间。

清理总结:哪些边界不要忽略

这个小实验可以帮我们理解 sched 的使用边界:

  1. 它适合单进程、本地、小规模任务,不适合分布式任务队列。
  2. 任务函数不要阻塞太久,否则后面的任务会被拖慢。
  3. 周期任务要有停止条件,尤其是在测试脚本里。
  4. 失败重试要限制次数,并把最终失败记录清楚。
  5. 如果任务必须跨重启保留,需要把任务状态放到文件、数据库或更专业的任务系统里。

总结一下,sched 的价值不是替代大型调度平台,而是给小工具一个足够清晰的时间队列。注册任务、轮询运行、观察输出、再补失败重试,这条路径很适合快速完成本地自动化实验。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
CSS sticky 不生效排查清单:从 top、overflow 到滚动容器逐层定位CSS sticky 不生效排查清单:从 top、overflow 到滚动容器逐层定位
上一篇
CSS sticky 不生效排查清单:从 top、overflow 到滚动容器逐层定位
Redis Key 生命周期治理趋势:从临时缓存到可观测资产
下一篇
Redis Key 生命周期治理趋势:从临时缓存到可观测资产
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    2739次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    2537次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    2479次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    2709次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    2655次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码