python - Running Celery worker inside an app context still raises "working outside of app context" error in task -
i using miguel grinberg's article set celery app factory pattern in order send email flask-mail. i've been calling various scripts use celery without issues. keep getting runtime error: working outside of application context following task though running worker inside app context. why getting error? how flask-mail work in celery?
email.py:
from flask import current_app, render_template flask.ext.mail import message . import celery, mail @celery.task def send_async_email(msg): mail.send(msg) def send_email(to, subject, template, **kwargs): current_app.test_request_context(): # used app_context() 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 celery import celery flask.ext.mail import mail 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 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 self.connect() 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 pass application context send_email method.
- moving send_async_email method tasks.py module rest of celery tasks reside.
- rendering templates outside of email methods , passing them arguments.
i able fix issue creating instance of flask application locally:
email.py:
from flask import render_template, current_app flask.ext.mail import message . import celery, mail, create_app @celery.task def send_async_email(msg): app = create_app('default' or 'development') # -> fixed 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)
Comments
Post a Comment