Skip to main content

Manually Managing Contexts

To manually manage the application and request context lifecycle outside of a standard request loop (such as in standalone scripts or unit tests), use the AppContext class. In this version of Flask, AppContext and RequestContext have been merged, meaning a single class handles both application-level and request-level data.

The most reliable way to manage a context is using a with statement. This ensures that push() and pop() are called correctly, even if an exception occurs.

from flask import Flask, current_app, g

app = Flask(__name__)

with app.app_context():
# current_app and g are now available
print(current_app.name)
g.database_connection = "connected"
# Context is automatically popped here

For testing scenarios that require request data (like request or session), use test_request_context():

from flask import Flask, request

app = Flask(__name__)

with app.test_request_context('/path', method='POST'):
# request and session are now available
assert request.path == '/path'
assert request.method == 'POST'

Manual Push and Pop

In rare cases where a with block is not feasible—such as when managing a context across multiple function calls or within a custom WSGI loop—you can call push() and pop() manually. You must use a try...finally block to ensure the context is popped.

from flask import Flask
from flask.ctx import AppContext

app = Flask(__name__)
ctx = app.app_context()

try:
ctx.push()
# Perform operations with current_app or g
finally:
ctx.pop()

When manually popping, you can pass an exception to pop(). This exception is then passed to functions registered with @app.teardown_appcontext or @app.teardown_request.

error = None
ctx = app.test_request_context()
try:
ctx.push()
# ... logic that might fail ...
except Exception as e:
error = e
raise
finally:
ctx.pop(error)

Managing Contexts in CLI Commands

When writing custom CLI commands using click, you can use the with_appcontext decorator to automatically manage the context for the duration of the command.

import click
from flask.cli import with_appcontext
from flask import current_app

@click.command("my-command")
@with_appcontext
def my_command():
click.echo(f"Running in {current_app.name}")

Internally, the CLI uses click.Context.with_resource() to manage the AppContext lifecycle, which is functionally equivalent to a with statement.

Troubleshooting and Best Practices

  • Nested Pushes: AppContext tracks nested pushes using an internal _push_count. Cleanup (teardown functions) only runs when the outermost context is popped.
  • Active Context Requirement: You can only pop() a context if it is the currently active context. Attempting to pop a context that is not at the top of the stack will raise a RuntimeError.
  • Session Access: If you create a context using app.app_context() (which lacks request data), attempting to access the session proxy will raise a RuntimeError. Use app.test_request_context() if session access is required.
  • Context Leaks: Always ensure pop() is called. In tests, failing to pop a context can lead to "leaked" state where current_app or g from one test persists into the next. Use the with statement to avoid this.
  • URL Generation: If you need to use url_for inside an app context without a request, you must configure SERVER_NAME in your application config.