Celery结合flask完成异步任务与定时任务
Celery 常用于 web 异步任务、定时任务等。
使用 redis 作为 Celery的「消息代理 / 消息中间件」。
这里通过Flask-Mail使用qq邮箱延时发送邮件作为示例
pip install celery
pip install redis
pip install Flask-Mail
1、使用flask发送邮件
使用 Flask-Mail 发送邮件需要进行一下配置,其中QQ邮箱授权码的获取方式如下所述:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'top-secret!'# Flask-Mail configuration
app.config['MAIL_SERVER'] = 'smtp.qq.com'
app.config['MAIL_PORT'] = 465
# 启用/禁用传输安全层加密
app.config['MAIL_USE_TLS'] = False
# 启用/禁用安全套接字层加密
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = '我的QQ邮箱@qq.com'
app.config['MAIL_PASSWORD'] = '我的QQ邮箱授权码'
app.config['MAIL_DEFAULT_SENDER'] = '我的QQ邮箱@qq.com'# Celery configuration
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'# Initialize extensions
mail = Mail(app)@app.route("/send_mail")
def index11():# sender:发件人 recipients:收件人msg = Message('Hello', sender = app.config['MAIL_DEFAULT_SENDER'], recipients = ['目标邮箱@qq.com'])msg.body = "来自python--flask框架发送的邮件内容~"mail.send(msg)#发送Message类对象的内容return "发送成功"
点进qq邮箱,在设置里面点击账号,向下滚动开启pop3服务获取授权码。
2、延时发送邮件
定义celery任务,与flask基本一样 只是前面多了修饰符@celery.task
@celery.task
def send_async_email(email_data):"""Background task to send an email with Flask-Mail."""msg = Message(email_data['subject'],sender=app.config['MAIL_DEFAULT_SENDER'],recipients=[email_data['to']])msg.body = email_data['body']with app.app_context():mail.send(msg)
@app.route('/', methods=['GET', 'POST'])
def index():if request.method == 'GET':return render_template('index.html', email=session.get('email', ''))email = request.form['email']session['email'] = email# send the emailemail_data = {'subject': 'Hello from Flask','to': email,'body': '来自python--flask框架延时发送的邮件内容~'}if request.form['submit'] == 'Send':# send right awaysend_async_email.delay(email_data)print('here!--')flash('Sending email to {0}'.format(email))else:# send in one minutesend_async_email.apply_async(args=[email_data], countdown=60)flash('An email will be sent to {0} in one minute'.format(email))return redirect(url_for('index'))
3、生成带有状态信息进度条的异步任务
# bind为True,会传入self给被装饰的方法
@celery.task(bind=True)
def long_task(self):"""带有进度条以及状态报告的 异步任务"""verb = ['正在', '准备', '目前', '处于', '进行']adjective = ['全速', '努力', '默默地', '认真', '快速']noun = ['打开', '启动', '修复', '加载', '检查']message = ''total = random.randint(10, 50) # 随机取10~50的一个随机数for i in range(total):selectnow = random.random()print(selectnow)# 拼接上面三个lsit 随机的生成一些状态描述if not message or selectnow < 0.25:message = '{0} {1} {2}...'.format(random.choice(verb),random.choice(adjective),random.choice(noun))# 更新Celery任务状态self.update_state(state='PROGRESS',meta={'current': i, 'total': total,'status': message})time.sleep(1)# 返回字典return {'current': 100, 'total': 100, 'status': '任务完成!','result': 42}@app.route('/longtask', methods=['POST'])
def longtask():task = long_task.apply_async()return jsonify({}), 202, {'Location': url_for('taskstatus', task_id=task.id)}@app.route('/status/<task_id>')
def taskstatus(task_id):task = long_task.AsyncResult(task_id)# print(task.state)if task.state == 'PENDING':# PENDING的时候 如果一直PENDING可能是celery没开启response = {'state': task.state,'current': 0,'total': 1,'status': 'Pending...'}elif task.state != 'FAILURE':# 加载的时候response = {'state': task.state,'current': task.info.get('current', 0),'total': task.info.get('total', 1),'status': task.info.get('status', '')}if 'result' in task.info:response['result'] = task.info['result']else:# 报错时候的输出response = {'state': task.state,'current': 1,'total': 1,'status': str(task.info), # this is the exception raised}return jsonify(response)
4、完整代码
文件结构
--- current--- templates--- index.html--- asyn_001.py
这个是asyn_001.py
import os
import random
import time
from flask import Flask, request, render_template, session, flash, redirect, \url_for, jsonify
from flask_mail import Mail, Message
from celery import Celeryapp = Flask(__name__)
app.config['SECRET_KEY'] = 'top-secret!'# Flask-Mail configuration
app.config['MAIL_SERVER'] = 'smtp.qq.com'
app.config['MAIL_PORT'] = 465
# 启用/禁用传输安全层加密
app.config['MAIL_USE_TLS'] = False
# 启用/禁用安全套接字层加密
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = '我的QQ邮箱@qq.com'
app.config['MAIL_PASSWORD'] = '我的QQ邮箱授权码'
app.config['MAIL_DEFAULT_SENDER'] = '我的QQ邮箱@qq.com'# Celery configuration
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'# Initialize extensions
mail = Mail(app)@app.route("/send_mail")
def index11():# sender:发件人 recipients:收件人msg = Message('Hello', sender = app.config['MAIL_DEFAULT_SENDER'], recipients = ['目标邮箱@qq.com'])msg.body = "来自python--flask框架发送的邮件内容~"mail.send(msg)#发送Message类对象的内容return "发送成功"# Initialize Celery
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)@celery.task
def send_async_email(email_data):"""Background task to send an email with Flask-Mail."""msg = Message(email_data['subject'],sender=app.config['MAIL_DEFAULT_SENDER'],recipients=[email_data['to']])msg.body = email_data['body']with app.app_context():mail.send(msg)@app.route('/', methods=['GET', 'POST'])
def index():if request.method == 'GET':return render_template('index.html', email=session.get('email', ''))email = request.form['email']session['email'] = email# send the emailemail_data = {'subject': 'Hello from Flask','to': email,'body': '来自python--flask框架延时发送的邮件内容~'}if request.form['submit'] == 'Send':# send right awaysend_async_email.delay(email_data)print('here!--')flash('Sending email to {0}'.format(email))else:# send in one minutesend_async_email.apply_async(args=[email_data], countdown=60)flash('An email will be sent to {0} in one minute'.format(email))return redirect(url_for('index'))# bind为True,会传入self给被装饰的方法
@celery.task(bind=True)
def long_task(self):"""带有进度条以及状态报告的 异步任务"""verb = ['正在', '准备', '目前', '处于', '进行']adjective = ['全速', '努力', '默默地', '认真', '快速']noun = ['打开', '启动', '修复', '加载', '检查']message = ''total = random.randint(10, 50) # 随机取10~50的一个随机数for i in range(total):selectnow = random.random()print(selectnow)# 拼接上面三个lsit 随机的生成一些状态描述if not message or selectnow < 0.25:message = '{0} {1} {2}...'.format(random.choice(verb),random.choice(adjective),random.choice(noun))# 更新Celery任务状态self.update_state(state='PROGRESS',meta={'current': i, 'total': total,'status': message})time.sleep(1)# 返回字典return {'current': 100, 'total': 100, 'status': '任务完成!','result': 42}@app.route('/longtask', methods=['POST'])
def longtask():task = long_task.apply_async()return jsonify({}), 202, {'Location': url_for('taskstatus', task_id=task.id)}@app.route('/status/<task_id>')
def taskstatus(task_id):task = long_task.AsyncResult(task_id)# print(task.state)if task.state == 'PENDING':# PENDING的时候 如果一直PENDING可能是celery没开启response = {'state': task.state,'current': 0,'total': 1,'status': 'Pending...'}elif task.state != 'FAILURE':# 加载的时候response = {'state': task.state,'current': task.info.get('current', 0),'total': task.info.get('total', 1),'status': task.info.get('status', '')}if 'result' in task.info:response['result'] = task.info['result']else:# 报错时候的输出response = {'state': task.state,'current': 1,'total': 1,'status': str(task.info), # this is the exception raised}return jsonify(response)if __name__ == '__main__':app.run(debug=True)
这个是index.html
<html><head><title>Flask + Celery 示例</title><style>.progress {width: 100%;text-align: center;}</style></head><body><h1>Flask + Celery 示例</h1><h2>Example 1: 发送异步邮件</h2>{% for message in get_flashed_messages() %}<p style="color: red;">{{ message }}</p>{% endfor %}<form method="POST"><p>Send test email to: <input type="text" name="email" value="{{ email }}"></p><input type="submit" name="submit" value="Send"><input type="submit" name="submit" value="Send in 1 minute"></form><hr><h2>Example 2: 生成进度条以及状态报告</h2><!--<button οnclick="start_long_task();">Start Long Calculation</button><br><br>--><button id="start-bg-job">Start Long Calculation</button><br><br><div id="progress"></div><script src="//cdnjs.cloudflare.com/ajax/libs/nanobar/0.2.1/nanobar.min.js"></script><script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script><script>function start_long_task() {// add task status elementsdiv = $('<div class="progress"><div></div><div>0%</div><div>...</div><div> </div></div><hr>');$('#progress').append(div);// create a progress barvar nanobar = new Nanobar({bg: '#44f',target: div[0].childNodes[0]});// send ajax POST request to start background job$.ajax({type: 'POST',url: '/longtask',success: function(data, status, request) {status_url = request.getResponseHeader('Location');console.log("status_url", status_url,"nanobar", nanobar, "div[0]", div[0])console.log("data", data)update_progress(status_url, nanobar, div[0]);},error: function() {alert('Unexpected error');}});}function update_progress(status_url, nanobar, status_div) {// send GET request to status URL$.getJSON(status_url, function(data) {// update UIpercent = parseInt(data['current'] * 100 / data['total']);nanobar.go(percent);$(status_div.childNodes[1]).text(percent + '%');$(status_div.childNodes[2]).text(data['status']);if (data['state'] != 'PENDING' && data['state'] != 'PROGRESS') {if ('result' in data) {// show result$(status_div.childNodes[3]).text('Result: ' + data['result']);}else {// something unexpected happened$(status_div.childNodes[3]).text('Result: ' + data['state']);}}else {// rerun in 2 secondssetTimeout(function() {update_progress(status_url, nanobar, status_div);}, 2000);}});}$(function() {$('#start-bg-job').click(start_long_task);});</script></body>
</html>
5、启动任务
终端cd到current文件夹所在目录

启动asyn_001程序,即可观察到异步任务的执行。
参考1 Celery实现异步任务和定时任务的简单示例
参考2 Using Celery with Flask
相关文章:
Celery结合flask完成异步任务与定时任务
Celery 常用于 web 异步任务、定时任务等。 使用 redis 作为 Celery的「消息代理 / 消息中间件」。 这里通过Flask-Mail使用qq邮箱延时发送邮件作为示例 pip install celery pip install redis pip install Flask-Mail1、使用flask发送邮件 使用 Flask-Mail 发送邮件需要进行…...
前端项目练习(练习-001-纯原生)
先创建一个空文件夹,名字为web-001,然后用idea开发工具打开,如图: 可以看到,这是个彻底的空项目,创建 index.html index.js index.css三个文件,如图: 其中,html文件内容如下&am…...
基于微信小程序的游戏账号交易买卖平台设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言系统主要功能:具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…...
2023 年 Bitget Wallet 测评
对Bitget Wallet钱包的看法 Bitget Wallet在安全性、产品实力和使用体验方面可与Metamask媲美,甚至有所超越,唯一稍显不足的是知名度稍逊一筹。在众多钱包中,Bitget Wallet是拥有最全面的钱包之一,尤其适合那些希望一步到位&…...
医疗图像分割指标
医疗图像其中两种图像格式:MRI(Magnetic Resonance Imaging,磁共振成像)、CT(Computed Tomography,计算机断层),常存成 .nii.gz 格式。都是 3D 的 H W L H \times W \times L HWL…...
零代码编程:用ChatGPT批量修改文件夹名称中的大小写
一个文件夹下面有很多个子文件夹,要把文件夹中的大写数字全部重命名为小写数字,比如将二 三 四,改成: 2 34 在ChatGPT中输入提示词如下: 你是一个Python编程专家,要完成一个文件夹重命名的任务。具体步骤如…...
webpack:详解cache模块常用配置
背景 持久化缓存算得上是 Webpack 5 最令人振奋的特性之一,它能够将首次构建结果持久化到本地文件系统,在下次执行构建时跳过一系列解析、链接、编译等非常消耗性能的操作,直接复用 module、chunk 的构建结果。 cache 会在开发模式被设置成…...
云原生Kubernetes:Pod控制器
目录 一、理论 1.Pod控制器 2.Deployment 控制器 3.SatefulSet 控制器 4.DaemonSet 控制器 5.Job 控制器 6.CronJob 控制器 二、实验 1.Deployment 控制器 2.SatefulSet 控制器 3.DaemonSet 控制器 4.Job 控制器 5.CronJob 控制器 三、问题 1. showmount -e 报错…...
数据库基础与MySQL入门
在当今的数字化世界中,数据如同生命之水,它贯穿于各种应用和服务中。尤其在游戏行业,例如经典的《三国志》,数据库管理成了一个不可或缺的环节。这不仅涉及到用户信息的存储,还涉及到游戏状态、积分、交易等复杂的数据处理需求。 MySQL作为一个广受欢迎的数据库管理系统,…...
探索Java爬虫框架:解锁网络数据之门
引言: 随着互联网时代的发展,大量的数据被存储在各种网页中。对于开发者而言,如何高效地获取和处理这些网络数据成为了一个重要的问题。而Java作为一门强大的编程语言,也有许多优秀的爬虫框架供开发者选择和使用。本文将带您深入…...
智慧燃气平台的总体架构到底应怎样设计?
关键词:智慧燃气、智慧燃气平台、智能燃气、智能监控 智慧燃气平台功能设计的一些方向和思考: 1、资源统一,管理调度 城市燃气智慧调度运营管理平台收集并且整理出每个业务系统信息,并且根据所整理出的信息结果制定出标准规范&…...
MonkeyRunner测试步骤
首先把安卓SDK的 环境变量给配置好,这里就不再多解释,自己google 然后将自己的安卓设备打开调试模式,USB连接至电脑,运行CMD,输入命令adb devices 查看你的安卓设备的ID(ID后面写程序会调用),…...
Konva基本处理流程和相关架构设计
前言 canvas是使用JavaScript基于上下文对象进行2D图形的绘制的HTML元素,通常用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。基于Canvas之上,诞生了例如 PIXI、ZRender、Fabric、Konva等 Canvas渲染引擎,兼顾易用的同时…...
人工智能AI知多少?
摘要 人工智能(Artificial Intelligence,简称AI)是一项前沿技术,正在快速发展并渗透到各个领域。然而,对于大多数人来说,人工智能仍然是一个陌生而复杂的概念。本文旨在对人工智能进行扫盲,介绍其基本概念、应用领域以及当前热门的人工智能模型。通过具体的例子,读者将…...
leetcode1610. 可见点的最大数目(java)
可见点的最大数目 题目描述滑动窗口 题目描述 难度 - 困难 leetcode1610. 可见点的最大数目 给你一个点数组 points 和一个表示角度的整数 angle ,你的位置是 location ,其中 location [posx, posy] 且 points[i] [xi, yi] 都表示 X-Y 平面上的整数坐标…...
Apache Flume
Flume 1.9.0 Developer Guide【Flume 1.9.0开发人员指南】 Introduction【介绍】 摘自:Flume 1.9.0 Developer Guide — Apache Flume Overview【概述】 Apache Flume is a distributed, reliable, and available system for efficiently collecting, aggregati…...
【切片】基础不扎实引发的问题
本次文章主要是来聊聊关于切片传值需要注意的问题,如果不小心,则很容易引发线上问题,如果不够理解,可能会出现奇奇怪怪的现象 问题情况: 小 A 负责一个模块功能的实现,在调试代码的时候可能不仔细&#x…...
CVE-2023-5129 libwebp堆缓冲区溢出漏洞影响分析
漏洞简述 近日苹果、谷歌、Mozilla和微软等公司积极修复了libwebp组件中的缓冲区溢出漏洞,相关时间线如下: 9月7日,苹果发布紧急更新,修复了此前由多伦多大学公民实验室报告的iMessage 0-click 漏洞,漏洞被认为已经被…...
leetcode做题笔记155. 最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…...
蓝海彤翔亮相2023新疆网络文化节重点项目“新疆动漫节”
9月22日上午,2023新疆网络文化节重点项目“新疆动漫节”(以下简称“2023新疆动漫节”)在克拉玛依科学技术馆隆重开幕,蓝海彤翔作为国内知名的文化科技产业集团应邀参与此次活动,并在美好新疆e起向未来动漫展映区设置展…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
