python基于celery实现异步任务周期任务定时任务


Posted in Python onDecember 30, 2019

这篇文章主要介绍了python基于celery实现异步任务周期任务定时任务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

hello, 小伙伴们, 好久不更新了,这一次带来的是celery在python中的应用以及设置异步任务周期任务和定时任务的步骤,希望能给入坑的你带来些许帮助.

首先是对celery的介绍,Celery其实是一个专注于实时处理和调度任务的分布式任务队列,同时提供操作和维护分布式系统所需要的全部数据, 因此可以用它提供的接口快速实现并管理一个分布式的任务队列,它本身不是任务队列,它是封装了操作常见任务队列的各种操作, 可以使用它快速进行任务队列的使用与管理.在Python中的组成部分是 1.用户任务 app 2.管道 broker 用于存储任务 官方推荐的是 redis rabbitMQ / backend 用于存储任务执行结果的 3, 员工 worker 大致流程入下:

python基于celery实现异步任务周期任务定时任务

最左边的是用户, 用户发起1个请求给服务器, 要服务器执行10个任务,将这10个任务分给10个调度器,即开启10个线程进行任务处理,worker会一直监听调度器是否有任务, 一旦发现有新的任务, 就会立即执行新任务,一旦执行完就会返回给调度器, 即backend, backend会将请求发送给服务器, 服务器将结果返回给用户, 表现的结果就是,这10个任务同时完成,同时返回,,这就是Celery的整个工作流程, 其中的角色分别为,任务(app_work), 调度器(broker + backend), 将任务缓存的部分, 即将所有任务暂时存在的地方,相当于生产者, 消费者(worker 可以指定数量, 即在创建worker命令的时候可以指定数量), 在worker拿到任务后,人就控制不了了, 除非把worker杀死, 不然肯定会执行完.

也即 任务来了以后, 调度器(broker)去缓存任务, worker去执行任务, 完成后返回backend,接着返回,

还有就是关于定时任务和周期任务在linux上为什么不用自身所带着的去做,是因为linux周期定时任务是不可控的, 不好管理, 返回值保存也是个麻烦事, 而celery只要开启着调度器, 就可以随时把人物结果获取到,即使用celery控制起来是非常方便的.

接下来就是实例代码:

workers.py

from celery import Celery
import time
# 创建一个Celery实例, 就是用户的应用app 第一个参数是任务名称, 可以随意起 后面的就是配置的broker和backend
diaoduqi= Celery("mytask", broker="redis://127.0.0.1:6379", backend="redis:127.0.0.1:6379")
# 接下来是为应用创建任务 ab
@diaoduqi.task
def ab(a,b):
  time.sleep(15)
  return a+b

brokers.py

from worker import ab

# 将任务交给Celery的Worker执行
res = ab.delay(2,4)

#返回任务ID
print(res.id)

backends.py

from celery.result import AsyncResult
from worker import diaoduqi

# 异步获取任务返回值
async_task = AsyncResult(id="31ec65e8-3995-4ee1-b3a8-1528400afd5a",app=diaoduqi)

# 判断异步任务是否执行成功
if async_task.successful():
  #获取异步任务的返回值
  result = async_task.get()
  print(result)
else:
  print("任务还未执行完成")

为了方便,现在直接将三个文件代表的部分命名在文件名称中.首先是启动workers.py

启动方式是依据系统的不同来启动的, 对于linux下 celery worker -A workers -l INFO 也可以指定开启的worker数量 即在后面添加的参数是 -c 5 表示指定5个worker 理论上指定的worker是无上限的,

在windows下需要安装一个eventlet模块进行运行, 不然不会运行成功 pip install eventlet 可以开启线程 不指定数量是默认6个worker, 理论上worker的数量可以开启无限个,但是celery worker -A s1 -l INFO -P eventlet -c 5 使用eventlet 开启5个worker 执行

该命令后 处于就绪状态, 需要发布任务, 即brokers.py进行任务发布, 方法是使用delay的方式执行异步任务, 返回了一个任务id, 接着去backends.py中取这个任务id, 去查询任务是否完成,判定条件即任务.successful 判断是否执行完, 上面就是celery异步执行任务的用法与解释

接下来就是celery在项目中的应用

在实际项目中应用celery是有一定规则的, 即目录结构应该如下.

python基于celery实现异步任务周期任务定时任务

结构说明 首先是创建一个CeleryTask的包,接着是在里面创建一个celery.py,必须是这个文件 关于重名的问题, 找寻模块的顺序是先从当前目录中去寻找, 根本找不到,接着是从内置模块中去找, 根本就找不到写的这个celery这个文件,

celery.py

from celery import Celery
DDQ = Celery("DDQ",broker="redis://127.0.0.1:6379",backend="redis://127.0.0.1:6379",
       include=["CeleryTask.TaskOne","CeleryTask.TaskTwo"])

TaskOne.py

import time
from CeleryTask.celery import DDQ
@DDQ.task
def one1(a,b):
  # time.sleep(3)
  return a+b
@DDQ.task
def one2():
  time.sleep(2)
  return "one2"

taskTwo.py

import time
from CeleryTask.celery import DDQ
@DDQ.task
def two1():
  time.sleep(2)
  return "two1"
@DDQ.task
def two2():
  time.sleep(3)
  return "two2"

getR.py

from CeleryTask.TaskOne import one1 as one

# one.delay(10,10)
# two.delay(20,20)

# 定时任务我们不在使用delay这个方法了,delay是立即交给task 去执行
# 现在我们使用apply_async定时执行

# 首先我们要先给task一个执行任务的时间
import datetime, time

# 获取当前时间 此时间为东八区时间
ctime = time.time()
# 将当前的东八区时间改为 UTC时间 注意这里一定是UTC时间,没有其他说法
utc_time = datetime.datetime.utcfromtimestamp(ctime)
# 为当前时间增加 10 秒
add_time = datetime.timedelta(seconds=10)
action_time = utc_time + add_time

# action_time 就是当前时间未来10秒之后的时间
# 现在我们使用apply_async定时执行
res = one.apply_async(args=(6, 10), eta=action_time)
res = one.apply_async(args=(6, 10), eta=action_time)
res = one.apply_async(args=(6, 10), eta=action_time)
res = one.apply_async(args=(6, 10), eta=action_time)
res = one.apply_async(args=(6, 10), eta=action_time)
res = one.apply_async(args=(6, 10), eta=action_time)
print(res.id)
# 这样原本延迟5秒执行的One函数现在就要在10秒钟以后执行了

接着是在命令行cd到与CeleryTask同级目录下, 使用命令 celery worker -A CeleryTask -l INFO -P eventlet -c 50 这样 就开启了worker 接着去 发布任务, 在定时任务中不再使用delay这个方法了,

delay是立即交给ttask去执行, 在这里使用 apply_async定时执行 指的是调度的时候去定时执行

需要设置的是UTC时间, 以及定时的时间(多长时间以后执行) 之后使用 celery worker -A CeleryTask -l INFO -P eventlet -c 50 命令开启worker, 之后运行 getR.py文件发布任务, 可以看到在定义的时间以后执行该任务

周期任务

周期任务 指的是在指定时间去执行任务 需要导入的一个模块有 crontab

文件结构如下

python基于celery实现异步任务周期任务定时任务

结构同定时任务差不多,只不过需要变动一下文件内容 GetR文件已经不需要了,可以删除.

celery.py

from celery import Celery
from celery.schedules import crontab

DDQ = Celery("DDQ", broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379",
       include=["CeleryTask.TaskOne", "CeleryTask.TaskTwo"])

# 我要要对beat任务生产做一个配置,这个配置的意思就是每10秒执行一次Celery_task.task_one任务参数是(10,10)
DDQ.conf.beat_schedule = {
  "each10s_task": {
    "task": "CeleryTask.TaskOne.one1",
    "schedule": 10, # 每10秒钟执行一次
    "args": (10, 10)
  },
  "each1m_task": {
    "task": "CeleryTask.TaskOne.one2",
    "schedule": crontab(minute=1) # 每1分钟执行一次 也可以替换成 60 即 "schedule": 60
  }
}

TaskOne.py

import time
from CeleryTask.celery import DDQ
@DDQ.task
def one1(a,b):
  # time.sleep(3)
  return a+b
@DDQ.task
def one2():
  time.sleep(2)
  return "one2"

taskTwo.py

import time
from CeleryTask.celery import DDQ
@DDQ.task
def two1():
  time.sleep(2)
  return "two1"
@DDQ.task
def two2():
  time.sleep(3)
  return "two2"

以上配置完成以后,这时候就不能直接创建worker了,因为要执行周期任务,需要首先有一个任务的生产方, 即 celery beat -A CeleryTask, 用来产生创建者, 接着是创建worker worker的创建命令还是原来的命令, 即 celery worker -A CeleryTask -l INFO -P eventlet -c 50 , 创建完worker之后, 每10秒就会由beat创建一个任务给 worker去执行.至此, celery创建异步任务, 周期任务,定时任务完毕, 伙伴们自己拿去测试吧.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中用于去除空格的三个函数的使用小结
Apr 07 Python
python单元测试unittest实例详解
May 11 Python
python机器学习之随机森林(七)
Mar 26 Python
Python基于辗转相除法求解最大公约数的方法示例
Apr 04 Python
浅谈django的render函数的参数问题
Oct 16 Python
Python3标准库总结
Feb 19 Python
python字符串替换第一个字符串的方法
Jun 26 Python
Python跳出多重循环的方法示例
Jul 03 Python
Python实现TCP通信的示例代码
Sep 09 Python
centos+nginx+uwsgi+Django实现IP+port访问服务器
Nov 15 Python
Django2 连接MySQL及model测试实例分析
Dec 10 Python
Pycharm导入anaconda环境的教程图解
Jul 31 Python
Django框架之中间件MiddleWare的实现
Dec 30 #Python
Django 路由层URLconf的实现
Dec 30 #Python
python解析多层json操作示例
Dec 30 #Python
pytorch 求网络模型参数实例
Dec 30 #Python
利用python3 的pygame模块实现塔防游戏
Dec 30 #Python
pytorch 批次遍历数据集打印数据的例子
Dec 30 #Python
python多线程使用方法实例详解
Dec 30 #Python
You might like
PHP针对常规模板引擎中与CSS/JSON冲突的解决方法
2014/08/19 PHP
PHP正则表达式入门教程(推荐)
2016/05/18 PHP
PHP面向对象之工作单元(实例讲解)
2017/06/26 PHP
详解PHP中curl_multi并发的实现
2020/06/08 PHP
utf8的编码算法 转载
2006/12/27 Javascript
学习YUI.Ext 第二天
2007/03/10 Javascript
javascript让setInteval里的函数参数中的this指向特定的对象
2010/01/31 Javascript
jquery 问答知识整理
2010/02/11 Javascript
JS维吉尼亚密码算法实现代码
2010/11/09 Javascript
javascript避免数字计算精度误差的方法详解
2014/03/05 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
2014/08/20 Javascript
jQuery标签替换函数replaceWith()的使用例子
2014/08/28 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
多个js毫秒倒计时同时进行效果
2016/01/05 Javascript
JavaScript引用类型和基本类型详解
2016/01/06 Javascript
限制只能输入数字的实现代码
2016/05/16 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
2016/10/04 Javascript
微信小程序 UI与容器组件总结
2017/02/21 Javascript
Angular2使用Guard和Resolve进行验证和权限控制
2017/04/24 Javascript
javascript用rem来做响应式开发
2018/01/13 Javascript
JavaScript中Array方法你该知道的正确打开方法
2018/09/11 Javascript
原生js实现分页效果
2020/09/23 Javascript
基于Python实现对PDF文件的OCR识别
2016/08/05 Python
Django rest framework基本介绍与代码示例
2018/01/26 Python
idea创建springMVC框架和配置小文件的教程图解
2018/09/18 Python
python列表使用实现名字管理系统
2019/01/30 Python
Python类的继承、多态及获取对象信息操作详解
2019/02/28 Python
Python这样操作能存储100多万行的xlsx文件
2019/04/16 Python
Python中新式类与经典类的区别详析
2019/07/10 Python
详解python使用金山词霸的翻译功能(调试工具断点的使用)
2021/01/07 Python
pycharm进入时每次都是insert模式的解决方式
2021/02/05 Python
BLACKMORES澳洲官网:澳大利亚排名第一的保健品牌
2018/09/27 全球购物
美国运动鞋类和服装零售连锁店:Shoe Palace
2019/08/13 全球购物
班主任对学生的评语
2014/04/26 职场文书
党员转正意见怎么写
2015/06/03 职场文书
Python中threading库实现线程锁与释放锁
2021/05/17 Python