Skip to main content

Contexts & Global Proxies

Flask uses a context system to make certain objects globally accessible within a specific thread or task without requiring them to be passed as arguments to every function. This system ensures that data like the current request or application configuration is isolated between concurrent requests.

The Context System

The core of this system is the AppContext class, located in src/flask/ctx.py. In Flask 3.2, the previously separate RequestContext was merged into AppContext. An AppContext instance serves as a container for all state related to a single "execution unit," which is typically an HTTP request or a CLI command.

When a context is active, it is stored in a contextvars.ContextVar named _cv_app (defined in src/flask/globals.py). This allows Flask to remain thread-safe and compatible with asynchronous tasks, as each concurrent execution path maintains its own reference to the active context.

Context Lifecycle

The lifecycle of a context is managed through push() and pop() methods. During a standard request, the Flask.wsgi_app method (in src/flask/app.py) handles this automatically:

# Simplified view of src/flask/app.py
def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
try:
ctx.push()
response = self.full_dispatch_request(ctx)
# ... handle response ...
finally:
ctx.pop()

When push() is called, the context is set in the _cv_app variable. When pop() is called, Flask executes teardown functions registered via teardown_appcontext or teardown_request. As of Flask 3.2, all teardown functions are executed even if one fails, using an ExceptionGroup on supported Python versions to ensure resources are cleaned up reliably.

Global Proxies

To provide a convenient API, Flask exposes several "global" variables that are actually werkzeug.local.LocalProxy objects. These proxies redirect all attribute access and method calls to the object currently active in the AppContext.

The primary proxies defined in src/flask/globals.py are:

  • current_app: Points to the Flask application instance (ctx.app).
  • request: Points to the current Request object (ctx.request).
  • session: Points to the current session (ctx.session).
  • g: Points to the _AppCtxGlobals instance (ctx.g).

If you attempt to access these proxies when no context is pushed, Flask raises a RuntimeError with a descriptive message (e.g., "Working outside of application context").

Accessing the Underlying Object

Because proxies wrap the actual objects, they can occasionally interfere with libraries that perform type checking or require a real object reference. In such cases, you can use the _get_current_object() method provided by the proxy:

from flask import current_app

# Get the actual Flask instance instead of the proxy
app_instance = current_app._get_current_object()

Per-Request Storage with g

The g object (an instance of _AppCtxGlobals from src/flask/ctx.py) is a dedicated namespace for storing data during a context. It is frequently used to manage resources like database connections that should be created on demand and closed when the request ends.

A common pattern, seen in the flaskr tutorial (examples/tutorial/flaskr/db.py), involves using g to cache a connection and a teardown handler to close it:

from flask import current_app, g

def get_db():
if "db" not in g:
g.db = sqlite3.connect(
current_app.config["DATABASE"],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db

def close_db(e=None):
db = g.pop("db", None)
if db is not None:
db.close()

def init_app(app):
# Register the teardown handler
app.teardown_appcontext(close_db)

Manual Context Management

While Flask manages contexts automatically during requests, you must often push them manually in tests or CLI scripts to access proxies like url_for or current_app.

Application Context

Use app.app_context() to push a context that has application information but no request data:

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

Request Context

Use app.test_request_context() to simulate a request environment, which is essential for testing view logic or generating URLs that require request state:

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

Background Tasks and Context Copying

If you need to execute a function in a separate thread or task (e.g., using gevent or threading) while maintaining access to the current request's data, you can use copy_current_request_context. This decorator captures the active AppContext and pushes a copy of it when the decorated function is called.

from flask import copy_current_request_context

@app.route("/")
def index():
@copy_current_request_context
def background_task():
# This can safely access flask.request
do_work(request.remote_addr)

gevent.spawn(background_task)
return "Task started"

This is implemented in src/flask/ctx.py by calling original.copy(), which creates a new AppContext sharing the same underlying request and session objects.