Celery注册装饰器@app.task和@shared_task

news2024/9/29 15:25:11

注册装饰器

@app.task和@shared_task是Celery中用于定义任务的两种不同装饰器, 它们之间存在明显的区别.
from celery import Celery  
 
app = Celery('my_app', broker='amqp://guest@localhost//')  
 
@app.task  
def my_task():  
    # 任务逻辑  
    pass

from celery import shared_task  
 
@shared_task  
def add(x, y):  
    return x + y
以下是这两者的详细比较:
* 1. 定义与用途.
     - @app.task: 这是Celery库提供的装饰器, 用于在具体的Celery应用程序中定义任务. 
     当创建一个Celery应用程序对象(通常命名为 app), 并使用@app.task装饰器来定义任务函数时,
     这些任务函数仅在该特定的Celery应用程序中可用.
     - @shared_task: 这是Celery提供的另一个装饰器, 用于定义共享任务(shared task).
     共享任务是指可以在多个Celery应用程序之间共享的任务.
     通过使用@shared_task装饰器, 可以在一个Celery应用程序中定义任务, 并将其标记为共享任务,
     以便其他使用相同配置的Celery应用程序可以直接导入和使用该任务.

* 2. 依赖性与可移植性.
     - @app.task: 任务依赖于特定的Celery应用程序实例.
       因此, 如果在不同的Celery应用程序中想要使用相同的任务, 需要在每个应用程序中都重新定义它.
       这在单个项目或单个Celery应用程序的上下文中很有用, 但不利于跨项目的代码复用.
     - @shared_task: 不依赖于特定的Celery应用程序实例.
       它加载到内存后会自动添加到Celery对象中, 因此可以在多个Celery应用程序之间共享.
       这使得任务的可移植性和可重用性更强, 特别是在多个项目或组件需要共享通用任务时.
       
* 3. 使用场景.
     - 如果任务仅在特定的Celery应用程序中使用, 那么使用@app.task就足够了.
     - 如果任务需要在多个Celery应用程序之间共享, 或者想要提高任务的代码复用性和可维护性, 那么使用@shared_task会更合适.

* 4. 注意事项.
     - 当使用@shared_task时, 请确保所有相关的Celery应用程序都已正确配置, 
       并且它们使用相同的消息代理(: RabbitMQ, Redis等)和结果后端(如果需要的话).
     - 无论是@app.task还是@shared_task, 定义的任务都可以异步执行, 并可以返回结果.
       可以使用delay()方法或apply_async()方法来异步调用这些任务.
通过一个具体的例子来说明任务在多个Celery应用程序之间共享. 
假设你有两个Python项目, 它们都需要执行一些通用的后台任务, 比如发送电子邮件, 处理图片上传等.
这些任务在逻辑上是相似的, 因此希望避免在两个项目中重复编写相同的代码.
使用@app.task的情况需要会在每个Django项目的Celery配置中分别定义这些任务. 
例如, 在第一个项目中:
# Project 1  
from celery import Celery  
  
app = Celery('project1', broker='amqp://guest@localhost//')  
  
@app.task  
def send_email(recipient, subject, body):  
    # 发送电子邮件的逻辑  
    pass
然后在第二个项目中, 需要再次定义相同的任务:
# Project 2  
from celery import Celery  
  
app = Celery('project2', broker='amqp://guest@localhost//')  
  
@app.task  
def send_email(recipient, subject, body):  
    # 发送电子邮件的逻辑(与Project 1中的完全相同)  
    pass
这种方法的问题在于, 如果发送电子邮件的逻辑需要更新, 需要在两个项目中都进行更改, 这增加了维护的复杂性和出错的风险.
使用@shared_task, 可以在一个独立的Python模块或包中定义这些共享任务, 并在需要时从两个项目中导入它们.
注意: 使用@shared_task, 多个Celery应用程序必须连接到同一个消息代理(Redis等中间件), 或者至少能够互相通信的消息代理.
只要它们都能连接到同一个消息代理实例或兼容的实例集, 任务就可以被正确发送和接收.
先说明一下@shared_task的绑定任务特性:
from celery import Celery, shared_task


# 创建共享任务
@shared_task
def add(x, y):
    return x + y


print(add.app)  # <Celery default at 0x148b1a83e50>

# 创建app1实例
app1 = Celery(broker='amqp://')
print(add.app is app1)  # True
print(add.app)  # <Celery __main__ at 0x148b4281700>

# 创建app2实例
app2 = Celery(broker='redis://')
print(add.app is app2)  # True 
print(add.app)  # <Celery __main__ at 0x148b4295d30>

调用@shared_task饰后的add任务, 它会尝试找到一个已经存在的Celery应用实例.
(通常是通过查找当前模块或父模块中的celery应用实例, '如果有多个则使用离调用最近的').
如果没有找到, 它会创建一个新的默认Celery应用实例. 这个新创建的实例将绑定到被装饰的任务上, 并通过task.app属性访问.

代码中, 首先定义了一个add任务, 然后创建了app1和app2两个Celery应用实例.
add任务在app1和app2创建之前就已经被定义, 并且由于此时还没有显式创建Celery应用实例,
@shared_task装饰器会创建一个默认的Celery应用实例并将其绑定到add任务上.

在定义Celery实例之后, 调用饰后的add任务, 那么它会自动将任务重新绑定到最近Celery实例上.
了解情况后可以继续进行实验了.
首先, 创建一个包含共享任务的模块(例如, shared_tasks.py):
# shared_tasks.py  
from celery import shared_task


@shared_task
def add(x, y):
    return x + y

image-20240804202251739

然后, 在第一个Python项目中导入共享任务:
# p1.py  
from celery import Celery
from shared_task import add  # 导入共享任务

app = Celery('project1',
             broker='redis://localhost:6379/0')  # Redis作为Broker

# 可以通过app.tasks来访问任务, 比如检查它是否已经注册
print(add.name in app.tasks)  # 输出True

image-20240804202351424

启动Celery Worker进程: celery -A p1  worker --loglevel=info  -P eventlet
在第二个Django目中导入这个共享任务:
# p2.py  
from celery import Celery
from shared_task import add  # 导入共享任务

app = Celery('project2',
             broker='redis://localhost:6379/1')  # Redis作为Broker

# 可以通过app.tasks来访问任务, 比如检查它是否已经注册
print(add.name in app.tasks)  # 输出True

image-20240804202439161

并启动Celery Worker进程: celery -A p2  worker --loglevel=info  -P eventlet
定义一个脚本使用提交任务, 使用标识符为project1的Celery实例作为配置:
# p3.py
from p1 import add  # 调用add任务时, 会自动绑定p1文件中的celery实例

result = add.delay(4, 4)  # 使用.delay()方法异步触发任务
print(f'任务ID:: {result.id}')

image-20240804202503043

再定义一个脚本使用提交任务, 使用标识符为project1的Celery实例作为配置:
# p4.py
from p2 import add  # 调用add任务时, 会自动绑定p2文件中的celery实例

result = add.delay(5, 5)  # 使用.delay()方法异步触发任务
print(f'使用结果ID触发的任务: {result.id}')

image-20240804202525754

分别运行脚本p3, p4两次, 查看消息日志:

image-20240804200819352

这样, 如果发送电子邮件的逻辑需要更新, 只需在shared_tasks.py中进行更改, 
然后两个项目都会自动使用更新后的逻辑, 而无需在每个项目中分别进行更改.
这大大提高了代码的复用性和可维护性.
如果将两个Celery实例配置为使用同一个消息中间件, 
这些实例可以共享任务队列, worker就是随机的了(一个累死累活, 另外一个不干活).
# p1
# ...
app = Celery('project1',
BROKER_CONNECTION_RETRY_ON_STARTUP=True,
broker='redis://localhost:6379/0') 

# p2
# ...
app = Celery('project2',
BROKER_CONNECTION_RETRY_ON_STARTUP=True,
broker='redis://localhost:6379/0') 

image-20240804201454073

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1980351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构——双链表详解(超详细)

前言&#xff1a; 小编在之前已经写过单链表的创建了&#xff0c;接下来要开始双链表的讲解了&#xff0c;双链表比单链表要复杂一些&#xff0c;不过确实要比单链表更好进行实现&#xff01;下面紧跟小编的步伐&#xff0c;开启今天的双链表之旅&#xff01; 目录 1.概念和结构…

Pixart LED调变开发笔记

Pixart提供基础的鼠标和键盘代码, 开发者可以基于此快速的建置自己的firmware, application, 以下介绍代码中用来控制LED的API函式. 常亮模式 (Always on) 常亮模式, 调用API "pwm_led_set_always_on" 及 channel 来设置对应LED常亮. 闪烁模式 (Flash mode) 闪烁模…

华为OD机试 - 字符串编码校验(Java 2024 D卷 100分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华…

Unity3D 物体圆周运动

Unity3D 实现一个 2D 物体沿着圆周进行运动。 物体圆周运动 前段时间在开发一个小游戏时&#xff0c;需要实现火箭沿着一个圆形轨道进行圆周运动。 以前面试的时候也被问到过这类问题&#xff08;如何让一个 2D 物体做圆周运动&#xff09;&#xff0c;所以还是记录一下实现…

ICML 2024 | 矛与盾的较量!北大提出提示无关数据防御保护算法PID

文章链接&#xff1a;https://arxiv.org/pdf/2406.15305 代码地址&#xff1a;https://github.com/PKU-ML/Diffusion-PID-Protection 亮点直击 本文在实证观察中发现&#xff0c;保护阶段和利用阶段之间的提示不匹配可能会削弱当前数据保护算法的有效性。本文深入探讨了利用LDM…

【机器学习第7章——贝叶斯分类器】

机器学习第7章——贝叶斯分类器 7.贝叶斯分类器7.1贝叶斯决策论7.2 朴素贝叶斯分类器条件概率的m估计 7.3 极大似然估计优点基本原理 7.4 贝叶斯网络7.5 半朴素贝叶斯分类器7.6 EM算法7.7 EM算法实现 7.贝叶斯分类器 7.1贝叶斯决策论 一个医疗判断问题 有两个可选的假设&#…

从日常到专业,2024年必备在线翻译神器

现在全球交流越发的简单、频繁&#xff0c;很多时候外语成为了我们汲取新鲜知识的绊脚石。这时候我们就可以借助一些翻译在线的工具来解决这个问题。这次我们一起探索几款我搜集到的翻译工具。 1.福晰在线翻译 链接直通&#xff1a;https://fanyi.pdf365.cn/doc 这个工具支…

本地部署启动PmHub

文章目录 相关配置版本关系拉取代码使用Git clone下载源码 MYSQL配置Nacos配置Windows本地下载也可以Docker部署Nacos持久化配置启动Nacos访问Nacos Redis配置RocketMQ配置新建相应目录rocketmq, 然后在里面新建broker文件夹, 放broker.conf在 rocketmq 新建 data 文件夹&#…

MRAM FRAM在医疗设备场景的应用

便携式超声波扫描仪是一种检测从物体反射的声波并将其转换为实时图像的设备。通常使用配置存储器和图像/报告存储器两种类型的存储器。配置存储器存储来自外部硬件的标识和配置信息&#xff0c;图像/报告存储器存储图像和相应的报告数据。这些存储器即使在突然断电的情况下&…

MySQL介绍和安装与配置

文章目录 MySQL介绍什么是数据库什么是关系型数据库什么是非关系型数据库MySQL概述和历史 MySQL安装和配置在线安装方式MySQL5.7的安裝1.下载yum Repository2.安装yum Repository3.安装mysql5.7的服务3.后续命令 离线安装方式1、卸载已有的MySQL文件2、安装mysql3、后续命令 修…

详细分析Python生成项目依赖包的工具

目录 前言1. pipreqs2. pip freeze3. poetry4. conda5. 总结 前言 在Python项目开发中&#xff0c;管理依赖包是确保项目正常运行的关键步骤 本博客将详细分析几种流行的依赖管理工具&#xff0c;包括 pipreqs、pip freeze、poetry 和 conda&#xff0c;以及它们的使用场景和…

智能硬件创新实训平台-嵌入式、物联网、移动互联网、人工智能实验实训教学平台

智能硬件是继智能手机之后的一个科技概念&#xff0c;通过软硬件结合的方式&#xff0c;对传统设备进行改造&#xff0c;进而让其拥有智能化的功能。智能化之后&#xff0c;硬件具备连接的能力&#xff0c;实现互联网服务的加载&#xff0c;形成“云端”的典型架构&#xff0c;…

黑马Java零基础视频教程精华部分_11_面向对象进阶(3)_抽象类、接口、适配器

《黑马Java零基础视频教程精华部分》系列文章目录 黑马Java零基础视频教程精华部分_1_JDK、JRE、字面量、JAVA运算符 黑马Java零基础视频教程精华部分_2_顺序结构、分支结构、循环结构 黑马Java零基础视频教程精华部分_3_无限循环、跳转控制语句、数组、方法 黑马Java零基础视…

【Linux】文件变身大作战:Linux下的文件重命名艺术

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;文件变身大作战&#xff1a;Linux下的文件重命名艺术 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法…

OpenGL3.3_C++_Windows(33)

PBR渲染管线 Physically Based Rendering渲染管线 :使用一种更符合物理学规律的算法模型来模拟光线&#xff0c;由于它与物理性质非常接近&#xff0c;可以直接以物理参数为依据来编写表面材质判断是否基于物理的渲染,有三个数学模型&#xff1a;微平面&#xff0c;能量守恒&a…

Go语言实现支持泛型的二分查找算法

二分查找基本原理图&#xff1a; 参考代码&#xff1a; 泛型的定义&#xff1a; package v2024type Integer interface {int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 }type Float interface {float32 | float64 }type Number interface …

无需变更环境变量,一键管理和运行不同JDK版本的jar包

前言 之前公司的项目一直用的都是JDK8&#xff0c;然后前段时间&#xff0c;公司要求以后的新项目必须要用JDK17及以上的版本。但是以前的旧项目还有很多都在维护。 这样子的话&#xff0c;电脑上就至少有两个版本的JDK了。我想在不变动环境变量的情况下&#xff08;环境变量…

可穿戴设备与健康科技:迈向个性化医疗的未来

在数字化和智能化浪潮的推动下&#xff0c;可穿戴设备与健康科技正迅速改变我们的健康管理方式。这些设备不仅使我们能够实时监测健康指标&#xff0c;还为个性化医疗提供了宝贵的数据支持。本文将详细探讨可穿戴设备的作用、健康监测技术的发展、个性化医疗的趋势&#xff0c;…

代码随想录——买卖股票的最佳时机含冷冻期(Leetcode 309)

题目链接 动态规划 class Solution {public int maxProfit(int[] prices) {if(prices.length 0 || prices.length 1){return 0;}// 初始化int[][] dp new int[prices.length 1][2];dp[1][0] -prices[0];for(int i 2; i < prices.length; i){dp[i][0] Math.max(dp[…

Arduino PID库 (5):开启或关闭 PID 控制的影响

Arduino PID库 &#xff08;5&#xff09;&#xff1a;开启或关闭 PID 控制的影响 Arduino PID库 &#xff08;4&#xff09;&#xff1a;Reset Windup 问题 尽管拥有一个PID控制器很好&#xff0c;但有时你并不关心它要说什么。 PID On - User Overwritting Output&#x…