Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using celery with Flask app context gives "Popped wrong app context." AssertionError

I'm more or less using the setup to run Celery tasks using your flask app context from here: http://flask.pocoo.org/docs/0.10/patterns/celery/

I'm getting the same error message as Create, manage and kill background tasks in flask app

but, I'm getting it in the actual worker where the Celery task is being executed. Here is the trace:

worker_1 | Traceback (most recent call last):
worker_1 |   File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 240, in trace_task
worker_1 |     R = retval = fun(*args, **kwargs)
worker_1 |   File "/code/app/__init__.py", line 42, in __call__
worker_1 |     return TaskBase.__call__(self, *args, **kwargs)
worker_1 |   File "/usr/local/lib/python2.7/dist-packages/flask/ctx.py", line 186, in __exit__
worker_1 |     self.pop(exc_value)
worker_1 |   File "/usr/local/lib/python2.7/dist-packages/flask/ctx.py", line 178, in pop
worker_1 |     % (rv, self)
worker_1 | AssertionError: Popped wrong app context.  (<flask.ctx.AppContext object at 0x47a5790> instead of <flask.ctx.AppContext object at 0x427e390>)

Anyone have any ideas? Running in the app context should be fixing this problem, not creating it!

Thanks

like image 768
greegles Avatar asked Oct 21 '14 16:10

greegles


1 Answers

I know this is 4 years since you posted, but I was battling with a similar problem excep using rq not celery.

What everyone on the web tells you is that you need to add context to your app, eg as per the Supertutorial:

app = create_app()
app.app_context().push()

What they don't tell you is that if you have anything else in this file that will cause your primary instance of the app to open it (Eg another function), then you'll hit the 2 lines above and get the error.

My solution was to put the 2 lines inside of the actual async function that I'm offloading to a worker like this:

def run_async_backup(machine_id):
    app = create_app()
    app.app_context().push()
    # your code for the worker...

This means the primary instance won't hit them - while the worker will (assume only the worker calls this function).

like image 170
ilmoi Avatar answered Oct 30 '22 00:10

ilmoi