Python 定时任务(schedule, Apscheduler, celery, python-crontab)

本文对比了Python中的四个定时任务库:schedule、APScheduler、celery和python-crontab。介绍了它们的特点、优缺点,以及常见问题。schedule轻量级但不支持并行任务,APScheduler支持多种调度策略和后台存储,而celery适合分布式任务。文章还深入探讨了APScheduler的架构和工作原理。

背景

最近有个需求,需要实现一个定时或定期任务的功能,需要实现每月、每日、每时、一次性等需求,必须是轻量级不依赖其它额外组件,并能支持动态添加任务。

定时任务库对比

根据上面需求,从社区中找到了几个 Python 好用的任务调度库。有以下几个库:

  • schedule:Python job scheduling for humans. 轻量级,无需配置的作业调度库

  • python-crontab: 针对系统 Cron 操作 crontab 文件的作业调度库

  • Apscheduler:一个高级的 Python 任务调度库

  • Celery: 是一个简单,灵活,可靠的分布式系统,用于处理大量消息,同时为操作提供维护此类系统所需的工具, 也可用于任务调度

优缺点对比:

  • schedule 优点是简单、轻量级、无需配置、语法简单,缺点是阻塞式调用、无法动态添加或删除任务

  • Python-crontab 优点是针对于系统 crontab 操作,支持定时、定期任务,能够动态添加任务,不能实现一次性任务需求

  • Apscheduler 优点支持定时、定期、一次性任务,支持任务持久化及动态添加、支持配置各种持久化存储源(如 redis、MongoDB),支持接入到各种异步框架(如 gevent、asyncio、tornado)

  • Celery 支持配置定期任务、支持 crontab 模式配置,不支持一次性定时任务

schedule

Python 任务调度库,和 requests 库一样 for humans. 这个库也是最轻量级的一个任务调度库,schedule 允许用户使用简单、人性化的语法以预定的时间间隔定期运行Python函数(或其它可调用函数)。

直接使用 pip install schedule 进行安装使用,下面来看看官网给的示例:

	import schedule
	import time

	# 定义你要周期运行的函数
	def job():
		print("I'm working...")
	
	schedule.every(10).minutes.do(job) 				# 每隔 10 分钟运行一次 job 函数
	schedule.every().hour.do(job) 					# 每隔 1 小时运行一次 job 函数
	schedule.every().day.at("10:30").do(job) 		# 每天在 10:30 时间点运行 job 函数
	schedule.every().monday.do(job) 				# 每周一 运行一次 job 函数
	schedule.every().wednesday.at("13:15").do(job) 	# 每周三 13:15 时间点运行 job 函数
	schedule.every().minute.at(":17").do(job) 		# 每分钟的 17 秒时间点运行 job 函数
	
	while True:
		schedule.run_pending() 						# 运行所有可以运行的任务
		time.sleep(1)
schedule 常见问题
  1. 如何并行执行任务
    schedule 是阻塞式的,默认情况下, schedule 按顺序执行所有的作业,不能达到并行执行任务。如下所示:

    	import arrow
    	import schedule
    	
    	def job1():
    		print("job1 start time: %s" % arrow.get().format())
    		time.sleep(2)
    		print("job1 end time: %s" % arrow.get().format())
    	
    	def job2():
    		print("job2 start time: %s" % arrow.get().format())
    		time.sleep(5)
    		print("job2 end time: %s" % arrow.get().format())
    	
    	def job3():
    		print("job3 start time: %s" % arrow.<
<think>我们正在配置Celerycelery-redbeat集成,以实现基于Redis的持久化定时任务调度。以下是详细步骤: ###一、基础环境准备1. **安装依赖包**```bashpipinstall celerycelery-redbeatredis```2.**Redis配置**确保Redis服务已启动,并在Celery配置中设置Redis作为broker和backend。###二、Celery应用配置(`celery_config.py`)```python#celery_config.pybroker_url ='redis://localhost:6379/0'#Redis作为消息代理result_backend ='redis://localhost:6379/1'#Redis作为结果存储#RedBeat配置redbeat_redis_url= broker_url#使用同一个Redis实例存储调度计划redbeat_key_prefix= "redbeat:"#存储键前缀(默认值) ```###三、创建Celery应用(`app.py`)```python#app.pyfromcelery importCeleryfrom.celery_config import*app =Celery('redbeat_demo')app.config_from_object('celery_config')#设置RedBeat作为调度器app.conf.update(beat_scheduler='redbeat.RedBeatScheduler',#关键配置:指定RedBeat调度器)``` ###四、定义任务(`tasks.py`) ```python# tasks.pyfrom appimport app@app.task(bind=True, name='tasks.add')#注意:name必须与调度任务中的task字段匹配def add(self,a,b):returna+ b```###五、动态创建RedBeat调度任务(`scheduler.py`)```python#scheduler.pyfromredbeatimport RedBeatSchedulerEntryfromcelery.schedules importcrontabfrom appimport app#创建定时任务task_name= "task-add"#任务唯一标识entry= RedBeatSchedulerEntry(app=app,name=task_name,#存储在Redis中的键名(不含前缀)task='tasks.add',#必须与@app.task(name='tasks.add')一致schedule=crontab(minute='*/5'),#每5分钟执行一次args=(3,7),#任务参数enabled=True,#启用任务options={'queue':'add_queue'}#指定任务队列)entry.save()#保存到Redisprint(f"任务创建成功!Redis键名: redbeat:{task_name}") ```###六、启动Worker和Beat1. **启动Worker(指定队列)**```bashcelery -A appworker -Qadd_queue--loglevel=info``` 2. **启动Beat(使用RedBeat调度器)**```bashcelery -A appbeat --schedulerredbeat.RedBeatScheduler --loglevel=debug```###七、管理调度任务1.**删除任务**```python#在scheduler.py中执行key= 'redbeat:task-add'#完整键名= redbeat_key_prefix +task_nameentry =RedBeatSchedulerEntry.from_key(key, app=app)entry.delete()``` 2. **立即触发任务**```pythonfrom tasksimport addadd.delay(3,7)#异步执行``` 3. **终止运行中的任务**```pythonfromapp importappapp.control.revoke('任务ID',terminate=True)``` ###八、常见问题解决1. **任务未立即生效**RedBeat默认每分钟同步一次任务列表[^4],修改同步间隔:```python# celery_config.pyredbeat_lock_timeout =30#同步锁超时(秒)beat_max_loop_interval=10#最大同步间隔```2.**时区配置**在`celery_config.py`中设置:```pythontimezone ='Asia/Shanghai'enable_utc =False```>关键点:RedBeat通过Redis存储调度计划实现持久化,动态修改任务后需等待同步周期生效[^4]。 ---§§相关问题§§1.如何监控celery-redbeat的定时任务执行状态?2. celery-redbeat与原生Celery的beat_schedule配置有何区别?3.如何实现分布式环境下的RedBeat高可用?4. RedBeat调度任务出现重复执行应如何排查?</think>### Celerycelery-redbeat 集成配置详解 celery-redbeat 是基于 Redis 的持久化 Celery 调度器,支持动态管理定时任务。以下是完整配置流程: --- #### 一、基础环境配置 1. **安装依赖** ```bash pip install celery celery-redbeat redis ``` 2. **Redis 配置** 在 `celery_config.py` 中设置: ```python # Redis 作为 Broker 和结果后端 broker_url = 'redis://localhost:6379/0' result_backend = 'redis://localhost:6379/1' # RedBeat 专用配置 redbeat_redis_url = broker_url # 存储调度计划的 Redis redbeat_key_prefix = "redbeat:" # Redis 键前缀 redbeat_lock_timeout = 60 # 分布式锁超时() ``` --- #### 二、Celery 应用初始化 ```python # app.py from celery import Celery app = Celery('redbeat_demo') app.config_from_object('celery_config') # 加载配置文件 # 设置 RedBeat 为调度器 app.conf.update( beat_scheduler='redbeat.RedBeatScheduler', # 关键配置 beat_max_loop_interval=30, # 调度器最大循环间隔 ) ``` --- #### 三、动态任务管理(核心) ```python # scheduler.py from redbeat import RedBeatSchedulerEntry from celery.schedules import crontab, schedule from app import app # 导入Celery应用 def create_task(): entry = RedBeatSchedulerEntry( app=app, name="task-add", # 任务唯一标识 task='tasks.add', # 需与@app.task(name='tasks.add')匹配 schedule=crontab(minute='*/5'), # 每5分钟执行 args=(3, 11), # 位置参数 enabled=True, # 是否启用 options={"queue": "high_priority"} # 指定队列 ) entry.save() # 持久化到Redis print(f"任务已创建! Redis键: {app.conf.redbeat_key_prefix}{entry.name}") def delete_task(task_name): key = f"{app.conf.redbeat_key_prefix}{task_name}" entry = RedBeatSchedulerEntry.from_key(key, app=app) entry.delete() print(f"任务 {task_name} 已删除") ``` --- #### 四、任务定义(`tasks.py`) ```python from app import app @app.task(bind=True, name='tasks.add') # name必须与scheduler中的task一致 def add(self, x, y): print(f"执行加法: {x} + {y} = {x+y}") return x + y ``` --- #### 五、服务启动命令 1. **启动 Worker (需指定队列)** ```bash celery -A app worker -Q high_priority --loglevel=info ``` 2. **启动 Beat 调度器** ```bash celery -A app beat --scheduler redbeat.RedBeatScheduler --loglevel=debug ``` --- #### 六、高级管理技巧 1. **强制立即同步任务** 修改 `beat_max_loop_interval` 缩短同步周期(默认60秒): ```python # celery_config.py beat_max_loop_interval = 10 # 10秒同步一次 ``` 2. **时区配置(避免时间错乱)** ```python app.conf.timezone = 'Asia/Shanghai' app.conf.enable_utc = False ``` 3. **查看 Redis 中的任务** ```bash redis-cli keys "redbeat:*" ``` --- #### 七、完整工作流示例 ```python # 创建任务 create_task() # 执行scheduler.py中的函数 # 查看日志输出 # [redbeat] 任务 task-add 已存储到Redis # [celery] 每5分钟执行 tasks.add(3, 11) # 删除任务 delete_task("task-add") ``` > **注意**:修改任务后需等待调度器同步周期(默认60秒)[^4],可通过减小 `beat_max_loop_interval` 加速生效。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值