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起向未来动漫展映区设置展…...
【AI视野·今日NLP 自然语言处理论文速览 第四十四期】Fri, 29 Sep 2023
AI视野今日CS.NLP 自然语言处理论文速览 Fri, 29 Sep 2023 Totally 45 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MindShift: Leveraging Large Language Models for Mental-States-Based Problematic Smartphone Use Interve…...
【VsCode】vscode创建文件夹有小图标显示和配置
效果 步骤 刚安装软件后, 开始工作目录下是没有小图标显示的。 如下图操作,安装vscode-icons 插件,重新加载即可 创建文件夹,显示图标如下:...
celery分布式异步任务队列-4.4.7
文章目录 celery介绍兼容性简单使用安装使用方式 功能介绍常用案例获取任务的返回值任务中使用logging定义任务基类 任务回调函数No result will be storedResult will be stored任务的追踪、失败重试 python setup.py installln -s /run/shm /dev/shmOptional configuration, …...
解决M2苹果芯片Mac无法安装python=3.7的虚拟环境
问题描述 conda无法安装python3.7的虚拟环境: conda create -n py37 python3.7出现错误 (base) ➜ AzurLaneAutoScript git:(master) conda create -n alas python3.7.6 -y Collecting package metadata (current_repodata.json): done Solving environment: fa…...
Sound/播放提示音, Haptics/触觉反馈, LocalNotification/本地通知 的使用
1. Sound 播放提示音 1.1 音频文件: tada.mp3, badum.mp3 1.2 文件位置截图: 1.3 实现 import AVKit/// 音频管理器 class SoundManager{// 单例对象 Singletonstatic let instance SoundManager()// 音频播放var player: AVAudioPlayer?enum SoundOption: Stri…...
Oracle实现主键字段自增
Oracle实现主键自增有4种方式: Identity Columns新特性自增(Oracle版本≥12c)创建自增序列,创建表时,给主键字段默认使用自增序列创建自增序列,使用触发器使主键自增创建自增序列,插入语句&…...
【C++数据结构】二叉树搜索树【完整版】
目录 一、二叉搜索树的定义 二、二叉搜索树的实现: 1、树节点的创建--BSTreeNode 2、二叉搜索树的基本框架--BSTree 3、插入节点--Insert 4、中序遍历--InOrder 5、 查找--Find 6、 删除--erase 完整代码: 三、二叉搜索树的应用 1、key的模型 &a…...
TouchGFX之字体缓存
使用二进制字体需要将整个字体加载到存储器。 在某些情况下,如果字体很大,如大字号中文字体,则这样做可能不可取。 字体缓存使应用能够从外部存储器只能加载显示字符串所需的字母。 这意味着整个字体无需保存到在可寻址闪存或RAM上ÿ…...
windows系统关闭软件开机自启的常用两种方法
win10中安装软件时经常会默认开机自启动,本文主要介绍两种关闭软件开机自启动方法。 方法1 通过任务管理器设置 1.在任务管理器中禁用开机自启动:打开任务管理器,右键已启动的软件,选择禁用。 方法2 通过windows服务控制开机自启…...
巧用@Conditional注解根据配置文件注入不同的bean对象
项目中使用了mq,kafka两种消息队列进行发送数据,为了避免硬编码,在项目中通过不同的配置文件自动识别具体消息队列策略。这里整理两种实施方案,仅供参考! 方案一:创建一个工具类,然后根据配置文…...
wordpress设置缓存/淘宝运营培训班学费大概多少
我们以Android获取TP报点为例,分析poll过程。poll系统调用功能是检测设备是否有可读等对应事件发生时,调用read系统调用实现对设备的无阻塞访问。现在我们来分析poll的基本调用流程。 首先看应用如何使用poll: int main(int argc, char* argv[]) {int …...
帷客分享 wordpress/seo查询5118
以下为米尔科技工程师在使用DS-5过程中总结的经验步骤,一个简单的实用HelloWorld工程。虽然工程很简单,但是对于刚入门DS-5来说,可以起到一个指导的作用。如下:步骤:1、从开始菜单启动DS-5,可以看到DS-5的欢…...
网站添加对联广告代码/媒体发稿费用
2019独角兽企业重金招聘Python工程师标准>>> 摘要 原文:Brendan Greggs Blog :《Golang bcc/BPF Function Tracing》,31 Jan 2017引子:gdb、go execution tracer、GODEBUG、gctrace、schedtrace一、gccgo Function Counting二、Go…...
网站内部数据搜索怎么做/站长工具seo排名查询
目录树 新建Maven项目及步骤修改方法启动测试新建Maven项目及步骤 我这里是从创建开始讲,使用的工具是Idea2017版本。如果是已经创建了Maven,想改为spring boot项目的请直接跳到【修改方法】 1.点击右上角的File,出来的列表选择New Object&am…...
c2c网站特点/如何建立个人网址
一.堆分配参数(一)二.堆分配参数(二)...
静海的做网站/网络营销成功案例分析
【多选题】地层压力的表示方法有( )。A. 用压力的单位表示B. 用压力梯度表示C. 用当量钻井液密度表示D. 用压力系数表示【填空题】(第六章)现在工业上将黄铜和白铜之外的铜合金均称为 。【判断题】亚马逊服饰鞋包钟表首饰类商品信息检查表规定,Brand Name 是必填项,并且要将Bra…...