1. APScheduler
1.1 什么是 APScheduler?
APScheduler 是一个轻量级但功能强大的 Python 定时任务调度库,支持固定时间间隔、特定时间点或 Cron 式任务调度。它能与 FastAPI 无缝集成,用于后台执行周期性任务(如数据清理、邮件发送、报表生成等),而不会阻塞主线程。
1.2 在 FastAPI 中集成 APScheduler
- 后台任务自动化:避免手动触发重复性操作。
- 资源解耦:将耗时任务从 API 请求中分离,提升响应速度。
- 高可靠性:支持任务持久化和故障恢复机制。
- 灵活调度:通过 Cron 表达式实现复杂时间规则。
graph TD
A[FastAPI 启动] --> B[初始化 Scheduler]
B --> C[添加定时任务]
C --> D[任务执行]
D --> E[任务结果处理]
E --> F[关闭 Scheduler]
2. 基础集成步骤
2.1 安装依赖库
bash
pip install fastapi==0.109.0
pip install uvicorn==0.27.0
pip install apscheduler==3.10.4
pip install pydantic==2.5.1
2.2 核心代码实现
python
from fastapi import FastAPI
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from pydantic import BaseModel
# 定义 Pydantic 数据模型验证输入
class TaskRequest(BaseModel):
task_name: str
interval: int # 单位:秒
app = FastAPI()
scheduler = AsyncIOScheduler(jobstores={"default": MemoryJobStore()})
@app.on_event("startup")
async def init_scheduler():
"""应用启动时初始化调度器"""
scheduler.start()
print("Scheduler started")
@app.on_event("shutdown")
async def shutdown_scheduler():
"""应用关闭时安全停止调度器"""
scheduler.shutdown()
print("Scheduler stopped")
@app.post("/schedule")
async def add_task(request: TaskRequest):
"""添加定时任务接口"""
# 使用 Pydantic 自动校验 request 数据
job = scheduler.add_job(
execute_background_task,
"interval",
seconds=request.interval,
args=[request.task_name],
id=request.task_name
)
return {"status": "success", "job_id": job.id}
async def execute_background_task(task_name: str):
"""模拟后台任务执行"""
print(f"Executing task: {task_name} at {datetime.utcnow()}")
代码说明:
AsyncIOScheduler
:基于 asyncio 的调度器,避免阻塞主线程。MemoryJobStore
:默认内存存储(生产环境建议替换为 Redis 或 SQLAlchemy)。@app.on_event
:生命周期钩子管理调度器启停。- Pydantic 模型:自动校验 API 输入参数。
3. 高级应用场景
3.1 Cron 表达式调度
python
# 添加每日凌晨执行的任务
scheduler.add_job(
daily_report,
"cron",
hour=0,
minute=5,
id="daily_report"
)
3.2 异常处理与重试
python
from apscheduler.events import EVENT_JOB_ERROR
def error_listener(event):
"""全局任务异常监听"""
if event.exception:
print(f"Job crashed: {event.job_id}, error: {event.exception}")
scheduler.add_listener(error_listener, EVENT_JOB_ERROR)
3.3 持久化存储(使用 SQLite)
python
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
jobstores = {
"default": SQLAlchemyJobStore(url="sqlite:///jobs.sqlite")
}
scheduler = AsyncIOScheduler(jobstores=jobstores)
4. 课后 Quiz
-
问题 :如何在 APScheduler 中实现每周一上午 9 点执行任务?
答案:pythonscheduler.add_job(task, "cron", day_of_week="mon", hour=9)
-
问题 :任务意外中止后如何自动恢复?
答案 :使用持久化存储(如 SQLAlchemyJobStore)并在调度器初始化时添加
misfire_grace_time=300
参数。
5. 常见报错解决方案
报错 1:JobLookupError: No job by the id of ...
-
原因:操作了不存在的任务 ID。
-
解决方案 :
python# 操作前先检查任务是否存在 if scheduler.get_job(job_id): scheduler.remove_job(job_id)
报错 2:MaxIterationsReached
- 原因:Cron 任务迭代次数超出限制(通常因时间表达式错误导致)。
- 预防措施 :
- 使用在线工具校验 Cron 表达式(如 crontab.guru)。
- 避免在循环中添加重复任务。
报错 3:RuntimeError: Scheduler not running
-
原因:未正确初始化调度器生命周期。
-
修复方法 :
python# 确保在 startup 事件中启动 @app.on_event("startup") async def init(): scheduler.start()