赞
踩
flask项目中使用celery,有时遇到“working outside of application context”报错。究其原因是因为celery的实例app运行在与flask app 独立的进程空间,当在celery 任务中与flask app交互,会因为不存在flask的上下文抛出此异常
在执行flask app交互的逻辑前,使用 “with app.app_context():” 手动调用flask上下文,如在使用flask_mail模块发送邮件中(以下代码仅作演示,无法运行)
from flask_mail import Mail, Message app = Flask(__name__) app.config['MAIL_SERVER']='smtp.qq.com' # ...... 省略部分配置信息 app.config['CELERY_BROKER_URL']='redis://localhost:6379/0' app.config['CELERY_RESULT_BACKEND']='redis://localhost:6379/0' mail = Mail(app) 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']]) print(msg) msg.body = email_data['body'] with app.app_context(): # 如果缺少此行代码,抛出outside of application context异常 mail.send(msg)
如果在celery task逻辑中每涉及到flask app的交互,都要with app.app_context():,显然不是很方便,根据官方文档的推荐,将celery集成到flask中
from celery import Celery
def make_celery(app): # 将flask app当作参数传递给celery 的make函数
celery_app = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
celery_app.conf.update(app.config)
TaskBase = celery_app.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery_app.Task = ContextTask
return celery_app
示例
from flask import Flask
app = Flask(__name__)
app.config.update(
CELERY_BROKER_URL='redis://localhost:6379',
CELERY_RESULT_BACKEND='redis://localhost:6379'
)
celery = make_celery(app)
@celery.task()
def add_together(a, b):
return a + b
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。