Celery
执行流程
1.实例化app 2.app装饰几个任务 3.其他函数导入这个任务并使用 函数.delay
执行(此时并不是真正的执行而是将它放入broker中,如果这个时候worker启动,或者已经启动,他就立即执行) 4.得到结果放入redis中
程序运行
启动任务建议参考官方文档
由于没有任务所以程序一直停在哪里
添加任务
celery_test.py
@app.task # 用此装饰器装饰
def add(x, y):
print(f'正在计算{x},{y}的和.....')
return x + y
但是此方法并没有被添加到broker中,如果我们要将他添加到broker中
基本使用
获取id-方法一
1.celery -A celery_test worker -l info
让celery框架先跑起来
from celery import Celery
# broker任务队列
broker = 'redis://127.0.0.1:6379/1'
# redis下的第二个库,放在一个库的其实也没关系,也不会乱,但是这样更容易区分
backend = 'redis://127.0.0.1:6379/2' # 结构存储,执行完的结果存这里
app = Celery(__name__, broker=broker, backend=backend)
# 用命令执行
# celery -A celery_test worker -l info
# 添加任务
@app.task # 用此装饰器装饰
def add(x, y):
print(f'正在计算{x},{y}的和.....')
return x + y
2.执行函数名.delay
模块
from celery_test import add
# add(11,23) # 直接执行不会被添加到broker中
add.delay(3,4)
3.得到如下情况
获取id-方法二
执行函数名.delay
模块
from celery_test import add
# add(11,23) # 直接执行不会被添加到broker中
result = add.delay(3,4) # delay执行返回的就是uuid号
print(result)
------------------------------------------------------
7d27cc54-51e0-4ce6-87ed-805d9b7ae141
执行
from celery_test import app
from celery.result import AsyncResult
# 这是delay任务执行后 celery接收到并生成的uuid
id = '9f1d31a1-90b3-44ab-88f0-35efc6022d6b'
if __name__ == '__main__':
# async 现在是内置的关键字,用作声明后面的函数为 异步函数
# 这个类的作用是查询任务状态
# 也就是通过id和被app装饰的tast任务来定位,并查询状态,如果其中有错误,
# 就会按照下面自定义的显示状态内容。
async_one = AsyncResult(id=id, app=app)
# 成功执行
if async_one.successful():
# 通过实例化的get方法拿到结果
result = async_one.get()
print(result)
elif async_one.failed():
print('任务失败')
elif async_one.status == 'PENDING':
print('任务等待被执行')
elif async_one.status == 'RETRY':
print('任务异常后正在重试')
elif async_one.status == 'STARTED':
print('任务已经开始被执行')
-------------------------------------------------
7
推荐使用
1.创建一个celery的包,在包里存放相关的py文件,里面必须有一个名叫celery.py
文件celery_task.py
里面存放实例化的app,然后一个任务为一个py
文件,交给app管理。
此时celery_task
可以称之为一个celery
项目
# celery.py
from celery import Celery
broker = 'redis://localhost:6379/9'
backend = 'redis://localhost:6379/10'
# include是一个反射,里面是一个路径,只有被注册才能被管理
app = Celery(__name__, broker=broker, backend=backend, include=['celery_task.task1', 'celery_task.task2 '])
# task1.py
# 因为都在包内 所以可以使用 . 相对导入,
from .celery import app
@app.task
def add(x, y):
print(f'正在计算{x}和{y}的和......')
return x + y
# task2.py
from .celery import app
@app.task
def multiply(x, y):
print(f'正在计算{x}和{y}的积......')
return x * y
然后我们可以根据路径的相对导入来调用被celery管理的函数,我们启动的时候就要换一种方式了切换到scripts文件夹下启动celery项目包
然后就启动了
添加任务
from celery_task.task1 import add
# 只要能够通过这个路径导入模块执行delay就可以了
res = add.delay(99,88)
print(res) # 右键执行
-------------------------------------------
13f6b078-fd37-422d-934c-44ced9ae7705
结果仓库中
ps:如果celery后台没有启动则只有两个(celery -A celery_test worker -l info)
延时任务
添加延时任务
from datetime import datetime, timedelta
from celery_task.task1 import add
# 强类型
# 取了utc的当前时间 + 延迟时间(时间类型格式) 所以可以直接和时间格式相加
print(timedelta(seconds=10))
eta = datetime.utcnow() + timedelta(seconds=10)
# 执行延时任务
# add里需要几个参数 args里就放多少参数,然后后面etc存放utc时间,但是我们这里是东八区
# 如果我们直接填当前时间 会+8个小时
add.apply_async(args=(11, 88), eta=eta)
-------------------------------------------------
0:00:10
timedelta相关参数介绍
定时任务
既然是定时任务,那么认任务肯定是之前就被添加的,所以我们要放在 包下的celery.py
中
from celery import Celery
broker = 'redis://localhost:6379/9'
backend = 'redis://localhost:6379/10'
# include是一个反射,里面是一个路径,只有被注册才能被管理
app = Celery('Django', broker=broker, backend=backend, include=['celery_task.task1', 'celery_task.task2'])
# 执行定时任务
# 时区
app.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
app.conf.enable_utc = False
# 任务的定时配置
from datetime import timedelta
from celery.schedules import crontab
app.conf.beat_schedule = {
# 任务名称
'add_task': {
# 函数路径
'task': 'celery_task.task1.add',
# 每五秒执行函数add
'schedule': timedelta(seconds=5),
# 如果对定时要求的更复杂
# 'schedule':crontab(hour=8, day_of_week=1) # 每周一的八点执行
# 传参
'args': (1, 2)
}
}
此时我们执行celery -A celery_task worker -l info
是不行的任务并不会跑起来
任务并没有提交,worker只是在等待,所以我们还需要一条命令将任务提交 启动beat
celery -A celery_task beat -l info
这个时候任务才是真正被执行
我们也可以再redis中看到结果-执行了五次