I am using Miguel Greenberg's article to install celery with a factory application template for sending emails using Flask-Mail. I call various scripts that use Celery without any problems. However, I keep getting Runtime Error: working outside of application context with the following task, even if I run the worker inside the application context. Why am I getting this error? How to 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():
__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 tried:
- An attempt to pass the application context to the send_email method.
- Moving the send_async_email method to the tasks.py module, where the other tasks related to celery are located.
- Rendering templates outside email methods and passing them as arguments.