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 15 Python
Windows上使用virtualenv搭建Python+Flask开发环境
Jun 07 Python
浅谈Python 字符串格式化输出(format/printf)
Jul 21 Python
Python使用当前时间、随机数产生一个唯一数字的方法
Sep 18 Python
Python根据文件名批量转移图片的方法
Oct 21 Python
python调用外部程序的实操步骤
Mar 04 Python
关于Python 常用获取元素 Driver 总结
Nov 24 Python
python解析命令行参数的三种方法详解
Nov 29 Python
如何在python中执行另一个py文件
Apr 30 Python
Django Model中字段(field)的各种选项说明
May 19 Python
Python操作Excel的学习笔记
Feb 18 Python
pandas 操作 Excel操作总结
Mar 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
mysql 中InnoDB和MyISAM的区别分析小结
2008/04/15 PHP
PHP7+Nginx的配置与安装教程详解
2016/05/10 PHP
用javascript实现的激活输入框后隐藏初始内容
2007/06/29 Javascript
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
基于jquery的大众点评,分类导航实现代码
2011/08/23 Javascript
jquery重新播放css动画所遇问题解决
2013/08/21 Javascript
浅析document.ready和window.onload的区别讲解
2013/12/18 Javascript
javascript中attribute和property的区别详解
2014/06/05 Javascript
javascript实现加载xml文件的方法
2015/11/24 Javascript
vue+vue-validator 表单验证功能的实现代码
2017/11/13 Javascript
jQuery实现form表单序列化转换为json对象功能示例
2018/05/23 jQuery
vuex的module模块用法示例
2018/11/12 Javascript
vue实现的组件兄弟间通信功能示例
2018/12/04 Javascript
Vue中实现权限控制的方法示例
2019/06/07 Javascript
使用layer模态框给新页面传值的方法
2019/09/27 Javascript
node.js使用mongoose操作数据库实现购物车的增、删、改、查功能示例
2019/12/23 Javascript
基于Vue的侧边目录组件的实现
2020/02/05 Javascript
Node.js API详解之 assert模块用法实例分析
2020/05/26 Javascript
Vue 实现v-for循环的时候更改 class的样式名称
2020/07/17 Javascript
Vue.js中使用Vuex实现组件数据共享案例
2020/07/31 Javascript
Python使用scrapy采集数据过程中放回下载过大页面的方法
2015/04/08 Python
python获取从命令行输入数字的方法
2015/04/29 Python
python matplotlib实现双Y轴的实例
2019/02/12 Python
Python逐行读取文件中内容的简单方法
2019/02/26 Python
python实现京东订单推送到测试环境,提供便利操作示例
2019/08/09 Python
Python Pillow.Image 图像保存和参数选择方式
2020/01/09 Python
python GUI库图形界面开发之PyQt5单行文本框控件QLineEdit详细使用方法与实例
2020/02/27 Python
win10从零安装配置pytorch全过程图文详解
2020/05/08 Python
中国综合网上购物商城:苏宁易购
2016/08/09 全球购物
编程实现当输入某产品代码则打印出该产品记录的功能
2014/05/03 面试题
《登鹳雀楼》教学反思
2014/04/09 职场文书
教师批评与自我批评材料
2014/10/16 职场文书
优秀高中学生评语
2014/12/30 职场文书
写给医院的感谢信
2015/01/22 职场文书
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL
零基础学java之带参数以及返回值的方法
2022/04/10 Java/Android