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.
Using the Context Manager (Recommended)
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:
AppContexttracks 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 aRuntimeError. - Session Access: If you create a context using
app.app_context()(which lacks request data), attempting to access thesessionproxy will raise aRuntimeError. Useapp.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 wherecurrent_apporgfrom one test persists into the next. Use thewithstatement to avoid this. - URL Generation: If you need to use
url_forinside an app context without a request, you must configureSERVER_NAMEin your application config.