Skip to main content

Manually Managing Contexts

When you need to access Flask globals like current_app, g, request, or session outside of a standard request cycle—such as in a standalone script, a CLI command, or a unit test—you must manually manage an AppContext.

Using the Context Manager

The most reliable way to manage a context is using the with statement. This ensures that the context is automatically pushed when entering the block and popped when exiting, even if an exception occurs.

from flask import Flask, current_app

app = Flask(__name__)

with app.app_context():
# current_app and g are now available
print(current_app.name)

For scenarios requiring request-specific data like request.args or session, use test_request_context instead:

from flask import Flask, request

app = Flask(__name__)

with app.test_request_context("/?name=Flask"):
# request and session are now available
assert request.args["name"] == "Flask"

Manual Push and Pop

In some cases, such as complex test setups where the context lifecycle spans multiple function calls, you may need to call push() and pop() manually on the AppContext instance.

def test_manual_context_binding(app):
@app.route("/")
def index():
return f"Hello {flask.request.args['name']}!"

# Create the context object
ctx = app.test_request_context("/?name=World")

# Manually activate it
ctx.push()
try:
assert index() == "Hello World!"
finally:
# Always pop in a finally block to ensure teardown runs
ctx.pop()

Handling Teardown and Exceptions

When you manually call pop(), Flask executes all registered teardown functions (e.g., functions decorated with @app.teardown_appcontext or @app.teardown_request). If an unhandled exception occurred while the context was active, you should pass it to pop() so that teardown functions can handle it correctly.

ctx = app.app_context()
ctx.push()
try:
# Do work that might raise an exception
...
except Exception as e:
ctx.pop(e)
raise
else:
ctx.pop()

Managing Nested Contexts

Flask's AppContext uses a "push count" mechanism. If the same context object is pushed multiple times, it remains active until it has been popped an equal number of times. Teardown functions and signals like appcontext_popped only trigger when the push count reaches zero.

ctx = app.app_context()
ctx.push() # push_count = 1
ctx.push() # push_count = 2
ctx.pop() # push_count = 1, no teardown yet
ctx.pop() # push_count = 0, teardown functions run

Choosing the Right Context

Flask provides three methods on the Flask class to create an AppContext, depending on your needs:

  1. app.app_context(): Creates a context with only application-level data (current_app, g). Accessing request or session inside this context will raise a RuntimeError.
  2. app.test_request_context(*args, **kwargs): Creates a context that includes request and session data. It accepts the same arguments as Werkzeug's EnvironBuilder to simulate a specific request.
  3. app.request_context(environ): Creates a context from an existing WSGI environment. This is used internally by Flask and is rarely needed in application code.

[!IMPORTANT] As of Flask 3.2, RequestContext has been merged into AppContext. While the RequestContext alias still exists for backward compatibility, you should use AppContext for all manual context management.