python使用Flask,Redis和Celery的异步任务

news2024/9/22 17:18:55

 介绍

随着Web应用程序的发展和使用的增加,用例也变得多样化。我们现在正在建设和使用网站来执行比以往任何时候都更复杂的任务。其中一些任务可以进行处理,并将反馈立即转发给用户,而其他任务则需要稍后进行进一步处理和结果转发。越来越多地采用Internet访问和支持Internet的设备导致最终用户流量增加。

在本文中,我们将探讨Celery在Flask应用程序中安排后台任务的使用,以减轻资源密集型任务的负担并确定对最终用户的响应的优先级。

什么是任务队列?

任务队列是一种分配小的工作单元或任务的机制,可以在不干扰大多数基于Web的应用程序的请求-响应周期的情况下执行这些任务。

任务队列有助于委派工作,否则将在等待响应时降低应用程序的速度。它们还可以用于在主机或进程与用户交互时处理资源密集型任务。

示范 

我们将构建一个Flask应用程序,该应用程序允许用户设置提醒,该提醒将在设定的时间传递到他们的电子邮件中。

我们还将提供自定义消息或提醒被调用并将消息发送给用户之前的时间的功能。

设定

与其他项目一样,我们的工作将在虚拟环境中进行 :

$ pipenv install --three
$ pipenv shell

对于此项目,我们将需要安装Flask和Celery软件包以开始:

$ pipenv install flask celery

我们的Flask应用程序文件结构如下所示:

.
├── Pipfile                    #管理我们的环境
├── Pipfile.lock
├── README.md
├── __init__.py
├── app.py                     # Flask应用程序的主要实现
├── config.py                  # 托管配置
├── requirements.txt           # 储存我们的要求
└── templates
    └── index.html             # 登陆页面



1 directory, 8 files

让我们从创建Flask应用程序开始,该应用程序将呈现一个表单,该表单允许用户输入将来发送的消息的详细信息。

我们将以下内容添加到我们的app.py文件中:

from flask import Flask, flash, render_template, request, redirect, url_for

app = Flask(__name__)
app.config.from_object("config")
app.secret_key = app.config['SECRET_KEY']

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')

    elif request.method == 'POST':
        email = request.form['email']
        first_name = request.form['first_name']
        last_name = request.form['last_name']
        message = request.form['message']
        duration = request.form['duration']
        duration_unit = request.form['duration_unit']

        flash(“Message scheduled”)
        return redirect(url_for('index'))


if __name__ == '__main__':
    app.run(debug=True)

这是一个非常简单的应用程序,只需一条路由即可处理GETPOST请求表单。提交详细信息后,我们可以将数据交给计划工作的功能。

为了整理主应用程序文件,我们将配置变量放在单独的config.py文件中,然后从文件中加载配置:

app.config.from_object("config")

我们的config.py文件将与该app.py文件位于同一文件夹中,并包含一些基本配置:

SECRET_KEY = 'very_very_secure_and_secret'
# 更多配置

现在,让我们将目标网页实现为index.html


{% for message in get_flashed_messages() %}
  <p style="color: red;">{{ message }}</p>
{% endfor %}

<form method="POST">
    First Name: <input id="first_name" name="first_name" type="text">
    Last Name: <input id="last_name" name="last_name" type="text">
    Email: <input id="email" name="email" type="email">
    Message: <textarea id="textarea" name="message"></textarea>
    Duration: <input id="duration" name="duration" placeholder="Enter duration as a number. for example: 3" type="text">

   <select name="duration_unit">
      <option value="" disabled selected>Choose the duration</option>
      <option value="1">Minutes</option>
      <option value="2">Hours</option>
      <option value="3">Days</option>
   </select>

   <button type="submit" name="action">Submit </button>
</form>

 现在,我们可以启动我们的应用程序:

1_landing_page

使用邮件发送电子邮件

为了从Flask应用程序发送电子邮件,我们将使用Flask-Mail库,该库如下所示添加到我们的项目中:

$ pipenv install flask-mail

有了Flask应用程序和表单,我们现在可以将Flask-Mail集成到我们的app.py


from flask_mail import Mail, Message

app = Flask(__name__)
app.config.from_object("config")
app.secret_key = app.config['SECRET_KEY']

# 设置Flask-Mail集成

mail = Mail(app)

def send_mail(data):
    """ Function to send emails.
    """
    with app.app_context():
        msg = Message("Ping!",
                    sender="admin.ping",
                    recipients=[data['email']])
        msg.body = data['message']
        mail.send(msg)

功能 send_main(data)将接收要发送的消息和电子邮件的收件人,然后在经过指定的时间后将其调用以将电子邮件发送给用户。config.py为了使Flask-Mail正常运行,我们还需要向我们添加以下变量:


# Flask-邮件
MAIL_SERVER = 'smtp.googlemail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = 'mail-username'
MAIL_PASSWORD = 'mail-password'

 整合

在我们的Flask应用程序准备就绪并配备了电子邮件发送功能之后,我们现在可以集成Celery,以便计划在以后发送电子邮件。我们app.py将再次被修改:


# 现有导入保持不变


from celery import Celery

# Flask应用程序和flask-mail配置被截断



# 设置客户端


client = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
client.conf.update(app.config)

# 将此装饰器添加到我们的send_mail函数中


@client.task
def send_mail(data):
    #函数保持不变



@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')

    elif request.method == 'POST':
        data = {}
        data['email'] = request.form['email']
        data['first_name'] = request.form['first_name']
        data['last_name'] = request.form['last_name']
        data['message'] = request.form['message']
        duration = int(request.form['duration'])
        duration_unit = request.form['duration_unit']

        if duration_unit == 'minutes':
            duration *= 60
        elif duration_unit == 'hours':
            duration *= 3600
        elif duration_unit == 'days':
            duration *= 86400

        send_mail.apply_async(args=[data], countdown=duration)
        flash(f"Email will be sent to {data['email']} in {request.form['duration']} {duration_unit}")

        return redirect(url_for('index'))

celery通过附加消息传递代理的URL,我们导入并使用它在Flask应用程序中初始化Celery客户端。在我们的例子中,我们将使用Redis作为代理,因此我们将以下内容添加到我们的config.py

CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'

为了使我们的send_mail()功能作为后台任务执行,我们将添加@client.task装饰器,以便我们的Celery客户端会意识到这一点。

设置Celery客户端后,将修改还处理表单输入的主要功能。

首先,我们将send_mail()函数的输入数据打包在字典中。然后,我们使用函数通过Celery Task Calling API调用邮件功能,该函数apply_async接受函数所需的参数。

设置了一个可选countdown参数,定义了运行代码和执行任务之间的延迟。

汇集 

为了运行我们的项目,我们将需要两个终端,一个终端启动我们的Flask应用程序,另一个终端启动Celery worker,后者将在后台发送消息。

在第一个终端中启动Flask应用程序:

$ python app.py

在第二个终端中,启动虚拟环境,然后启动Celery worker:


# 启动virtualenv

$ pipenv shell
$ celery worker -A app.client --loglevel=info

如果一切顺利,我们将在运行Celery客户端的终端中获得以下反馈:

现在让我们导航到 http://localhost:5000并填写详细信息,以计划在提交2分钟后到达的电子邮件。

在表格上方,将显示一条消息,指示将接收电子邮件的地址以及发送电子邮件的持续时间。在我们的Celery终端中,我们还将能够看到一个日志条目,表明我们的电子邮件已被调度:

[2019-10-23 16:27:25,399: INFO/MainProcess] Received task: app.send_mail[d65025c8-a291-40d0-aea2-e816cb40cd78]  ETA:[2019-10-23 13:29:25.170622+00:00]

ETA条目的部分显示何时send_email()调用我们的函数,以及何时发送电子邮件。

 因此,让我们为后台任务实现一个监视解决方案,以便我们可以查看任务,并注意出现问题以及未按计划执行任务的情况。

 监控我们的群集

 安装Flower非常简单:

$ pipenv install flower

之前,我们在app.py文件中指定了Celery客户的详细信息。我们需要将该客户传递给Flower以对其进行监控。

为此,我们需要打开第三个终端窗口,进入虚拟环境,然后启动监视工具:

$ pipenv shell
$ flower -A app.client --port=5555

启动Flower时,我们通过将其传递给application(-A)参数来指定Celery客户端,并通过该参数来指定要使用的端口--port

有了我们的监控功能后,让我们安排在仪表板上发送另一封电子邮件,然后导航到http://localhost:5555,在以下位置我们会对此表示欢迎:

在此页面上,我们可以看到Celery集群中的工作人员列表,该列表当前仅由我们的机器组成。

要查看我们刚刚计划的电子邮件,请单击仪表板左上方的“ 任务”按钮,这将带我们到可以查看已计划的任务的页面:

在本部分中,我们可以看到我们已计划了两封电子邮件,并且已在计划的时间成功发送了一封电子邮件。出于测试目的,计划分别在1分钟和5分钟后发送电子邮件。

结论

我们已经成功建立了Celery集群并将其集成到我们的Flask应用程序中,该应用程序允许用户计划在将来的某个时间后发送电子邮件。


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

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

相关文章

冯诺依曼体系各硬件工作原理解析

文章目录计算机结构体系来源冯诺依曼体系结构主存储器的基本组成运算器的基本组成控制器的基本组成计算机的工作过程总结计算机结构体系来源 1946年,美国发明了世界上第一台计算机ENIAC,可用于比较快速的数据计算,但是其运算速度却受到了人工数据的输入速度的限制,为此我们现在…

NNDL实验 优化算法3D轨迹 鱼书例题3D版

这张图在网络上很流行。代码源自&#xff1a; 深度学习入门&#xff1a;基于Python的理论与实现 (ituring.com.cn) 2D版讲解&#xff1a;NNDL 作业11&#xff1a;优化算法比较 调整学习率等超参数&#xff0c;观察动画&#xff0c;可以加深对各种算法的理解。 配合实验的模型…

南方农业杂志南方农业杂志社南方农业编辑部2022年第19期目录

遗传育种 峨眉黑鸡遗传多样性及群体遗传结构分析 袁霞;刘方庆;文陇英;徐婧;廖光祥;王强胜;王湘; 1-7 栽培与植保《南方农业》投稿&#xff1a;cn7kantougao163.com 井窖式移栽烤烟前期地上部和地下部生长规律拟合分析 温明霞;郭发文;冯小芽;王军;刘京;彭剑涛;廉云; 8-1…

从进程的角度来看JVM的内存分布

JVM(下面JVM都是指代HotSpot)本质上是运行在操作系统上的一个C程序&#xff0c;本文会从这个角度来构建对于JVM内存的完整视角&#xff0c;以HotSpot这个JVM实现运行在Linux操作系统上进行分析&#xff0c;在分析的过程中会解释清楚一些不太好理解的概念&#xff0c;诸如堆外内…

双十二哪些数码好物值得入手?盘点双十二最值得入手的数码好物

双十二快到了&#xff0c;相信很多人像我一样想趁着年末入手数码产品&#xff0c;但又不知道什么值得入手。最近也听到很多人问&#xff0c;针对这个问题&#xff0c;我来给大家盘点双十二最值得入手的数码好物&#xff0c;有需要的可以当个参考。 一、南卡小音舱蓝牙耳机 推…

怎样批量查询网站是否被搜狗收录?批量查询网站搜狗收录的详细教程

怎样批量查询网站是否被搜狗收录&#xff1f;批量查询网站搜狗收录的详细教程 批量查询网站搜狗收录的的具体操作&#xff1a; 第一步、打开站长工具 第二步、添加需要查询的网站域名 第三步、勾选要查询的功能&#xff08;勾选搜狗是否收录和搜狗总收录) 第四步、提交查询 第…

手把手教你在Ubuntu22.04 上安装 Vivado、HLS、Vitis 2022.2版本

文章目录1 Vivado22.2 和 HLS 22.2 安装下载安装包执行.bin文件开始安装命令配置启动问题2 Vitis 22.2 安装3 卸载Xilinx我是 雪天鱼&#xff0c;一名FPGA爱好者&#xff0c;研究方向是FPGA架构探索和数字IC设计。欢迎来关注我的B站账号&#xff0c;我将定期更新IC设计教程。 …

手撕红黑树 | 变色+旋转你真的明白了吗?【超用心超详细图文解释 | 一篇学会Red_Black_Tree】

说在前面 我们也很久没有更新数据结构系列了&#xff0c;半年前博主重新深入学习了红黑树这个数据结构&#xff0c;一直想更新呈现给大家&#xff0c;最近也一直没有时间&#xff0c;今天红黑树它来了&#xff01; 博主为了这篇博客&#xff0c;做了很多准备&#xff0c;试了…

怎么修复老照片?给你推荐这几个修复方法

相信大家的家里都有老照片吧&#xff0c;那在你们翻看这些老照片的时候&#xff0c;有没有发现有些老照片变得有些破旧、泛黄、模糊等情况呢&#xff1f;看到这些情况&#xff0c;大家是不是会很心疼呢&#xff1f;因为这些老照片都充满了各种各样的回忆&#xff0c;根本拍不出…

Docker查看容器的初始启动命令参数的常见几种方式

1.在使用docker容器的过程中&#xff0c;经常需要查看容器启动的命令来看当时启动容器时候所用的参数&#xff0c;如果时间不是很久或者通过history命令就可以很容易的想起或查看到命令&#xff0c;一旦时间过了很久或history被清空那么就无法获取命令&#xff0c;如下所示dock…

cengbox2靶机(hydra爆破、公私钥免密登录)

环境准备 靶机链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;zdpr 虚拟机网络链接模式&#xff1a;桥接模式 攻击机系统&#xff1a;kali linux 2021.1 信息收集 1.arp-scan -l探测目标靶机ip 2.nmap -p- -A -T4 192.168.1.107 探测目标靶机开放端口和服务 …

Docker基本使用

1、centos7安装docker engine 参考文档&#xff1a;https://docs.docker.com/engine/install/centos/ &#xff08;1&#xff09;卸载之前的docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \…

Spring——AOP

Spring中的可插拔组件技术 Spring AOP Spring AOP——Aspect Oriented Programming 面向切面编程AOP 的做法是将通用的、与业务无关的功能抽象封装为切面层切面可配置在目标方法执行前后&#xff0c;做到即插即用 不修改源码对程序功能进行拓展 AoP的关键概念 Spring AoP 与A…

栈与队列3:有效的括号

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;20. 有效的括号 题目&#xff1a; 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&am…

怎样才能批量查询网站的谷歌PR权重?把手教你批量查询网站谷歌PR权重值

谷歌PR是Google排名运算法则&#xff08;排名公式&#xff09;的一部分&#xff0c;用来标识网页的等级/重要性。在计算网站排名时&#xff0c;PageRank会将网站的外部链接数考虑进去。一个网站的外部链接数越多其PR值就越高&#xff1b;外部链接站点的级别越高&#xff0c;网站…

docker安装nginx代理nacos2.1.2版本集群

目录 安装docker最新版本 创建一个docker network&#xff0c;使之固定docker局域ip docker安装mysql主从 配置挂载的my.cnf配置文件 进入mysql主数据库容器命令 登录主数据库创建用于从数据连接主数据的账号密码 输入show master status;查看master数据库状态 在从数据库…

基于训练和推理场景下的MindStudio高精度对比

摘要&#xff1a;MindStudio提供精度比对功能&#xff0c;支持Vector比对能力。本文分享自华为云社区《【MindStudio训练营第一季】MindStudio 高精度对比随笔》&#xff0c;作者&#xff1a;Tianyi_Li。 训练场景下&#xff0c;迁移原始网络 (如TensorFlow、PyTorch) &#x…

[附源码]Python计算机毕业设计SSM家纺商品展示平台(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

连锁门店进销存软件的用途

门店式经营对于很多经营有道的老板来说是第一步&#xff0c;在规模扩张中&#xff0c;生意越做越大。这时要想拓宽销路&#xff0c;让收益更上一层楼&#xff0c;连锁、分店确实是一种行之有效的方法。 多门店管理经营存在的长久性难点是决策性工作量激增&#xff0c;管理方面…

[附源码]计算机毕业设计勤工俭学管理小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…