在应用上下文中运行 Celery 辅助角色仍会在任务中引发"working outside of app context"错误



我使用Miguel Grinberg的文章来设置芹菜与应用程序工厂模式,以便用Flask-Mail发送电子邮件。我一直在调用使用芹菜没有任何问题的各种脚本。然而,我一直得到Runtime Error: working outside of application context与以下任务,即使我在一个应用程序上下文中运行工人。为什么会出现这个错误?我如何得到Flask-Mail工作在芹菜?

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()
错误:

C:Python27Scriptscelery.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:Python27libsite-packagesceleryapptrace.py", line 240, in trace_task
    R = retval = fun(*args, **kwargs)
  File "C:Python27libsite-packagesceleryapptrace.py", line 438, in __protected_call__
    return self.run(*args, **kwargs)
  File "<flask_project_path>appemail.py", line 10, in send_async_email
    mail.send(msg)
  File "C:Python27libsite-packagesflask_mail.py", line 491, in send
    with self.connect() as connection:
  File "C:Python27libsite-packagesflask_mail.py", line 508, in connect
    return Connection(app.extensions['mail'])
  File "C:Python27libsite-packageswerkzeuglocal.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "C:Python27libsite-packageswerkzeuglocal.py", line 297, in _get_current_object
    return self.__local()
  File "C:Python27libsite-packagesflaskglobals.py", line 34, in _find_app
    raise RuntimeError('working outside of application context')
RuntimeError: working outside of application context

I have try:

  • 试图将应用程序上下文传递给send_email方法。
  • 将send_async_email方法移动到tasks.py模块,其余的芹菜任务驻留在该模块中。
  • 在email方法之外呈现模板,并将它们作为参数传递。

我可以通过在本地创建一个flask应用程序实例来解决这个问题:

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)

相关内容

  • 没有找到相关文章

最新更新