Intro to Flask contexts

As I’ve continued building my web app in Flask, there are two error messages that I’ve been encountering repeatedly:

RuntimeError: working outside of application context

and

RuntimeError: working outside of request context

I decided to dig a little deeper into what these messages were telling me about Flask’s internals and came across this great Stack Overflow thread (finding much of Flask’s own documentation on the subject to be incoherent). I’ll summarize my findings at a very high level and explain how I resolved one of the errors I’d been having.

Here are some cool things about Flask:

  1. It allows you to run multiple applications from the same Python process. As explained in the Stack Overflow post, for example, you can have two Flask servers running, a frontend and backend, and launch them both from the same Python script.
  2. It gives you convenient access to the current application or the current request it is handling through objects that act like global variables/methods like requestcurrent_appurl_for.

This raises an important natural question: how do we reconcile (1) and (2)? For instance, if both applications have an /indexroute, how does url_for('/index') know which one to refer to? The answer is that these “global variables” are actually local contexts that Flask conveniently changes underneath the hood so that they always point to the correct thing. In fact, a Flask application always has two different contexts: an application context and a request context.

Generally speaking, the application context is the one present when the application is in its setup phase, and the request context is the one present when the application is handling an active request. Another awesome thing about Flask is that most of the time, we don’t have to worry about contexts because, from the Flask documentation:

whenever a request context is pushed, an application context will be created alongside if this is necessary. As a result, you can ignore the existence of the application context unless you need it.

In particular, inside view functions, application contexts are automatically provided if necessary. But, a problem might arise if you need to reference the current application in an external script. In the case of my application, I put the machine learning logic in an external script make_image.py in an external module that gets imported by my views.py module. But in a method inside make_image.py, I want to save images to a directory that is specified by the app’s configuration file:

TMP_DIR = current_app.config['INTERMEDIATE_IM_DIR']

which throws the first of the two error messages above. The issue is that since I’m not inside a view function, the application context is not created for me automatically alongside the request context I’m currently in, and Flask does not know where to look for the configuration. The solution is to manually create the application context as follows:

with app.app_context():
    TMP_DIR = current_app.config['INTERMEDIATE_IM_DIR']

Problem solved!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s