在应用上下文中运行芹菜工作者仍然提出“在应用上下文之外工作”任务错误 [英] Running Celery worker inside an app context still raises "working outside of app context" error in task

查看:349
本文介绍了在应用上下文中运行芹菜工作者仍然提出“在应用上下文之外工作”任务错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Miguel Grinberg的文章以应用程序工厂模式设置芹菜,以便用Flask-Mail发送电子邮件。我一直在调用使用芹菜的各种脚本,没有任何问题。然而,即使我正在应用程序上下文中运行worker,我仍然得到运行时错误:在应用程序上下文之外工作执行以下任务。为什么我得到这个错误?如何在Celery中使用Flask-Mail?



email.py

  from flask导入current_app,render_template $ b $ from flask.ext.mail导入消息
from。导入芹菜,邮件

@ celery.task
def send_async_email(msg):
mail.send(msg)

def send_email(to,subject ,template,** kwargs):
with current_app.test_request_context():#也使用了app_context()。
msg = Message(current_app.config ['PORTAL_MAIL_SUBJECT_PREFIX'] +''+ subject,
sender = current_app.config ['PORTAL_MAIL_SENDER'],recipients = [to])
msg.body = render_template(template +'.txt',** kwargs)
msg.html = render_template(template +'.html',** kwargs)
send_async_email.delay(msg)

__ init __。py

 从瓶子导入Flask $ b $从celery中导入Celery 
从flask.ext.mail中导入邮件
从配置导入配置

mail = Mail()
celery = Celery(__ name__,broker = config ['default']。CELERY_BROKER_URL)
$ b $ create_app(config_name):
app = Flask(__ name__)
app.config.from_object(config [config_name])
config [config_name] .init_app(app)
mail.init_app(app)$ b $ celery.conf .update(app.config)
app.register_bl ueprint(main_blueprint)
返回应用程序

celery_worker.py < code

$ b $ p $ import os
from app import celery,create_app

push()

$ b app = create_app(os.getenv('FLASK_CONFIG')or'default')
app.app_context
$ b

Error:

  C:\Python27\Scripts\celery.exe worker  - a celery_worker.celery --loglevel = info 

[2015-09-30 12:07:34,408:INFO / MainProcess]收到的任务:app.email.send_async_email [3ec772ff-4767-49cb-90ba- 445629da30da]
[2015-09-30 12:07:34,417:ERROR / MainProcess]任务app.email.send_async_email [3ec772ff-4767-49cb-90ba-445629da30da] raise unexpected:RuntimeError('working outside of application context ')
Traceback(最近一次调用最后一次):
文件C:\Python27\lib\site-packages\celery\app\trace.py,第240行,在trace_task
R = retval = fun(* args,** kwargs)
文件C:\Python27\lib\site-packages\celery\app\trace.py,第438行,在__protected_call__
中返回self.run(* args,** kwargs)
文件< flask_project_path> \app\email.py,第10行,在send_async_email
mail.send(msg)
文件C:\Python27\lib\site -packages \flask_mail.py,第491行,在
中用self.connect()作为连接:
文件C:\Python27\lib\site-packages\flask_mail。 py,第508行,连接
返回连接(app.extensions ['mail'])
文件C:\Python27\lib\site-packages\werkzeug\local。 py,第338行,在__getattr__
中返回getattr(self._get_current_object(),name)
文件C:\Python27\lib\site-packages\werkzeug\local.py ,第297行,在_get_current_object
中返回self .__ local()
文件C:\Python27\lib\site-packages\flask\globals.py,第34行,在_找_ app
引发RuntimeError('在应用程序上下文之外工作')
RuntimeError:在应用程序上下文之外工作

我尝试过:


  • 尝试将应用程序上下文传递给send_email方法。

  • 将send_async_email方法移动到一个tasks.py模块,其余的芹菜任务驻留在这个模块中。
  • 在电子邮件方法之外呈现模板并将它们作为参数传递。
  • li>

解决方案

我能够通过在本地创建瓶颈应用程序的实例来解决问题。 p>

email.py

 从flask导入render_template,current_app $ b $ from flask.ext.mail导入消息
from。导入芹菜,邮件,create_app

$ b @ celery.task
def send_async_email(msg):
app = create_app('default'或'development')# >使用app.app_context()固定

mail.send(msg)

$ b def send_email(to,subject,template,** kwargs):
app = current_app._get_current_object()
msg = Message(current_app.config ['PORTAL_MAIL_SUBJECT_PREFIX'] +''+ subject,
sender = current_app.config ['MAIL_USERNAME'],recipients = [to ])
msg.body = render_template(template +'.txt',** kwargs)
msg.html = render_template(template +'.html',** kwargs)
send_async_email。延迟(msg)


I am using Miguel Grinberg's article to set up Celery with the app factory pattern in order to send email with Flask-Mail. I've been calling various scripts that use Celery without any issues. However I keep getting Runtime Error: working outside of application context with the following task even though I am running the worker inside an app context. Why am I getting this error? How do I get Flask-Mail to work in Celery?

email.py:

from flask import current_app, render_template
from flask.ext.mail import Message
from . import celery, mail

@celery.task
def send_async_email(msg):
    mail.send(msg)

def send_email(to, subject, template, **kwargs):
    with current_app.test_request_context(): # used app_context() as well.
        msg = Message(current_app.config['PORTAL_MAIL_SUBJECT_PREFIX'] + ' ' +                                       subject,
                  sender=current_app.config['PORTAL_MAIL_SENDER'], recipients=[to])
        msg.body = render_template(template + '.txt', **kwargs)
        msg.html = render_template(template + '.html', **kwargs)
        send_async_email.delay(msg)

__init__.py:

from flask import Flask
from celery import Celery
from flask.ext.mail import Mail
from configuration import config

mail = Mail()
celery = Celery(__name__, broker=config['default'].CELERY_BROKER_URL)

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    mail.init_app(app)
    celery.conf.update(app.config)
    app.register_blueprint(main_blueprint)
    return app

celery_worker.py:

import os
from app import celery, create_app

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
app.app_context().push()

Error:

C:\Python27\Scripts\celery.exe worker -A celery_worker.celery --loglevel=info

[2015-09-30 12:07:34,408: INFO/MainProcess] Received task: app.email.send_async_email[3ec772ff-4767-49cb-90ba-445629da30da]
[2015-09-30 12:07:34,417: ERROR/MainProcess] Task app.email.send_async_email[3ec772ff-4767-49cb-90ba-445629da30da] raised unexpected: RuntimeError('working outside of application context',)
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\celery\app\trace.py", line 240, in trace_task
    R = retval = fun(*args, **kwargs)
  File "C:\Python27\lib\site-packages\celery\app\trace.py", line 438, in __protected_call__
    return self.run(*args, **kwargs)
  File "<flask_project_path>\app\email.py", line 10, in send_async_email
    mail.send(msg)
  File "C:\Python27\lib\site-packages\flask_mail.py", line 491, in send
    with self.connect() as connection:
  File "C:\Python27\lib\site-packages\flask_mail.py", line 508, in connect
    return Connection(app.extensions['mail'])
  File "C:\Python27\lib\site-packages\werkzeug\local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "C:\Python27\lib\site-packages\werkzeug\local.py", line 297, in _get_current_object
    return self.__local()
  File "C:\Python27\lib\site-packages\flask\globals.py", line 34, in _find_app
    raise RuntimeError('working outside of application context')
RuntimeError: working outside of application context

I have tried:

  • Trying to pass the application context to the send_email method.
  • Moving the send_async_email method to a tasks.py module where the rest of my celery tasks reside.
  • Rendering the templates outside of the email methods and passing them as arguments.

解决方案

I was able to fix the issue by creating an instance of the flask application locally:

email.py:

from flask import render_template, current_app
from flask.ext.mail import Message
from . import celery, mail, create_app


@celery.task
def send_async_email(msg):
    app = create_app('default' or 'development')  # -> fixed
    with app.app_context():
        mail.send(msg)


def send_email(to, subject, template, **kwargs):
    app = current_app._get_current_object()
    msg = Message(current_app.config['PORTAL_MAIL_SUBJECT_PREFIX'] + ' ' +     subject,
    sender=current_app.config['MAIL_USERNAME'], recipients=[to])
    msg.body = render_template(template + '.txt', **kwargs)
    msg.html = render_template(template + '.html', **kwargs)
    send_async_email.delay(msg)

这篇关于在应用上下文中运行芹菜工作者仍然提出“在应用上下文之外工作”任务错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆