前言前段时间工作中有个需求,就是把原来的定时任务改成用celery。原项目中的定时任务使用的是apscheduler。不过django和celery做正规教程,网上比较少,而且版本不匹配。最后按照网上的教程+仔细阅读celery官方文档多次,终于成功了。现在做一个快速实现django+celery定时任务的教程/记录。这三个组件的基础知识和安装不再赘述。直接进入配置。版本Django==3.1.4celery==5.0.5redis==3.5.3思路步骤配置celery定时任务的思路和步骤主要是创建celery实例配置任务编写任务函数启动woker和beat存储结果目录层次(供参考)django_demo#项目根目录├──scheduler#这是一个app│├──__init__.py│├──celery.py#实例化celery并指定config│├──config.py#Celery配置文件│└──tasks.py#任务函数celery.pyfrom__future__importabsolute_importfromceleryimportCeleryapp=Celery("scheduler",broker="redis://:12345@localhost:6379/1",backend="redis://:12345@localhost:6379/2",include=["scheduler.tasks"])app.config_from_object("scheduler.config")这个文件用来实例化celery,指定broker和backend为redis(可写配置文件)include是指向任务文件app.config_from_object()指定celery配置config.pyfrom__future__importabsolute_importfromdatetimeimporttimedeltaCELERY_TIMEZONE="亚洲/上海"CELERY_ENABLE_UTC=TrueCELERYBEAT_SCHEDULE={"test":{#任务名称,用于开发者识别"task":"scheduler.tasks.test",#task指向任务函数"schedule":timedelta(seconds=2),#调度时间也可以使用crontab"args":()#没有参数不能写},}这个文件可以写一些celery的配置,使用crontab通过CELERYBEAT_SCHEDULE加载定时任务的定时时间。例如:crontab(hour="*/24")表示每24小时执行一次,也可以指定时间。详见crontabtasks.py的使用方法fromscheduler.celeryimportapp@app.task()deftest():print("hello")returnNoneimportappmustbeimportedfromtheinstantiatedcelery.py.如果实例化文件不叫celery.py,或者对象不叫app,需要做相应的更改。任务函数需要用@app.task()修饰。如果不需要返回值,就不用写return。启动worker和beat的终端命令这里需要打开2个终端,也可以将它们一起写在liunxcelery-Ascheduler.celerybeat-linfo#Startbeatcelery-Ascheduler.celeryworker-linfoscheduler中的shell脚本中。celery根据目录和文件确定,请根据自己的项目更改-linfo:运行时输出日志如果是windows下启动,worker命令需要换成-Peventlet:windows下启动worker,其他系统删除(如果提示eventlet不可用,使用pip安装eventlet)celery-Ascheduler.celeryworker-linfo-Peventlet#在windows下启动worker以上是celery定时任务的简单配置中工作项目,代码需要尽量简洁。配置需要放在同一个通用配置文件中,项目分为开发环境和线上环境,所以我最终的django配置是这样的:django_demo#项目根目录├──settings|├──base.py#基本设置|├──develop.py#开发环境设置├──scheduler#这是一个app│├──__init__.py│├──celery.py#实例化celery并指定config│└──tasks.py#对于任务功能,我把上面config.py中的配置分别写到django中的settings文件中。1.设置:develop.py:BROKER_URL=redis_urlCELERY_RESULT_BACKEND=redis_url在开发环境中,配置开发使用的broker和backend,注意变量名不能错,否则celery无法识别redis_url是我们的redis端口,我这里写在其他地方,方便管理所有组件。也可以这样写:BROKER_URL="redis://:12345@localhost:6379/1"CELERY_RESULT_BACKEND="redis://:12345@localhost:6379/1"base.py:这里我写任务调度项目的基本配置。#celery配置和任务配置CELERY_TIMEZONE="Asia/Shanghai"CELERY_ENABLE_UTC=TrueCELERYBEAT_SCHEDULE={"job1":{"task":"scheduler.tasks.job1","schedule":crontab(minute=0,hour=3),},"job2":{"task":"scheduler.tasks.job2","schedule":crontab(hour="*/24"),},}2.芹菜.pyfrom__future__importabsolute_importimportosfromceleryimportCeleryprofile=os.environ.setdefault("PROFILE","production")os.environ.setdefault("DJANGO_SETTINGS_MODULE",f"demo.settings.{profile}")app=Celery("scheduler",include=["scheduler.jobs"])app.config_from_object("django.conf:settings")这里为了方便区别开发和线上,先设置整体环境。profile和os.environ.setdefault都是项目环境的设置。celery的主体还是app和app.config_from_object。可以发现我的Celery()里面的变量越来越少,越来越简洁了。这是因为我将这些元素写入了django的设置中。celery在实例化的时候会根据我配置的“django.conf:settings”查找对应的值。3.jobs.pyfromscheduler.celeryimportapp@app.task()defjob1():passdefjob2():pass总结:celery实现定时任务还是比较容易的。主要由三部分组成:celery的实例化、配置和任务配置、任务函数。关于配置,大家可以因地制宜,随处写。关键是三个文件引用的时候,没必要混淆。一是在实例化celery的时候,app.config_from_object()注意写我们的配置路径。一种是在配置文件中配置定时任务时的任务函数路径。另一个是task函数的装饰器@app.task()必须是Celery中的一个实例对象。显示正在执行的计划任务的输出。local是启动的workerlocal2是启动的beatbeat终端,运行时会一直打印发送任务成功。worker会一直输出任务接收成功,并在任务函数中返回返回值和输出。参考celery官方文档实现win10下django+celery定时任务保姆级教程
