Context Locals — Werkzeug Documentation (3.1.x)

# Context Locals

You may find that you have some data during each request that you want to use across functions. Instead of passing these as arguments between every function, you may want to access them as global data. However, using global variables in Python web applications is not thread safe; different workers might interfere with each others’ data.

Instead of storing common data during a request using global variables, you must use context-local variables instead. A context local is defined/imported globally, but the data it contains is specific to the current thread, asyncio task, or greenlet. You won’t accidentally get or overwrite another worker’s data.

The current approach for storing per-context data in Python is the `contextvars` module. Context vars store data per thread, async task, or greenlet. This replaces the older `threading.local` which only handled threads.

Werkzeug provides wrappers around `ContextVar` to make it easier to work with.

# Proxy Objects

`LocalProxy` allows treating a context var as an object directly instead of needing to use and check `ContextVar.get()`. If the context var is set, the local proxy will look and behave like the object the var is set to. If it’s not set, a `RuntimeError` is raised for most operations.

    from contextvars import ContextVar
    from werkzeug.local import LocalProxy

    _request_var = ContextVar("request")
    request = LocalProxy(_request_var)

    from werkzeug.wrappers import Request

    @Request.application
    def app(r):
        _request_var.set(r)
        check_auth()
        ...

    from werkzeug.exceptions import Unauthorized

    def check_auth():
        if request.form["username"] != "admin":
            raise Unauthorized()

Accessing `request` will point to the specific request that each server worker is handling. You can treat `request` just like an actual `Request` object.

`bool(proxy)` will always return `False` if the var is not set. If you need access to the object directly instead of the proxy, you can get it with the `_get_current_object()` method.

class werkzeug.local.LocalProxy(local, name=None, *, unbound_message=None)

  A proxy to the object bound to a context-local object. All operations on the proxy are forwarded to the bound object. If no object is bound, a `RuntimeError` is raised.

  Parameters:

    - local (ContextVar[T] | Local | LocalStack[T] | t.Callable[[], T]) – The context-local object that provides the proxied object.

    - name (str | None) – Proxy this attribute from the proxied object.

    - unbound_message (str | None) – The error message to show if the context-local object is unbound.

  Proxy a `ContextVar` to make it easier to access. Pass a name to proxy that attribute.

      _request_var = ContextVar("request")
      request = LocalProxy(_request_var)
      session = LocalProxy(_request_var, "session")

  Proxy an attribute on a `Local` namespace by calling the local with the attribute name:

      data = Local()
      user = data("user")

  Proxy the top item on a `LocalStack` by calling the local. Pass a name to proxy that attribute.

      app_stack = LocalStack()
      current_app = app_stack()
      g = app_stack("g")

  Pass a function to proxy the return value from that function. This was previously used to access attributes of local objects before that was supported directly.

      session = LocalProxy(lambda: request.session)

  `__repr__` and `__class__` are proxied, so `repr(x)` and `isinstance(x, cls)` will look like the proxied object. Use `issubclass(type(x), LocalProxy)` to check if an object is a proxy.

      repr(user)  # <User admin>
      isinstance(user, User)  # True
      issubclass(type(user), LocalProxy)  # True

  Changelog

  Changed in version 2.2.2: `__wrapped__` is set when wrapping an object, not only when wrapping a function, to prevent doctest from failing.

  Changed in version 2.2: Can proxy a `ContextVar` or `LocalStack` directly.

  Changed in version 2.2: The `name` parameter can be used with any proxied object, not only `Local`.

  Changed in version 2.2: Added the `unbound_message` parameter.

  Changed in version 2.0: Updated proxied attributes and methods to reflect the current data model.

  Changed in version 0.6.1: The class can be instantiated with a callable.

  _get_current_object: Callable[[], T]

    Return the current object this proxy is bound to. If the proxy is unbound, this raises a `RuntimeError`.

    This should be used if you need to pass the object to something that doesn’t understand the proxy. It can also be useful for performance if you are accessing the object multiple times in a function, rather than going through the proxy multiple times.

# Stacks and Namespaces

`ContextVar` stores one value at a time. You may find that you need to store a stack of items, or a namespace with multiple attributes. A list or dict can be used for these, but using them as context var values requires some extra care. Werkzeug provides `LocalStack` which wraps a list, and `Local` which wraps a dict.

There is some amount of performance penalty associated with these objects. Because lists and dicts are mutable, `LocalStack` and `Local` need to do extra work to ensure data isn’t shared between nested contexts. If possible, design your application to use `LocalProxy` around a context var directly.

class werkzeug.local.LocalStack(context_var=None)

  Create a stack of context-local data. This wraps a `ContextVar` containing a `list` value.

  This may incur a performance penalty compared to using individual context vars, as it has to copy data to avoid mutating the list between nested contexts.

  Parameters:

    context_var (ContextVar[list[T]] | None) – The `ContextVar` to use as storage for this local. If not given, one will be created. Context vars not created at the global scope may interfere with garbage collection.

  Changelog

  Changed in version 2.0: Uses `ContextVar` instead of a custom storage implementation.

  Added in version 0.6.1.

  push(obj)

    Add a new item to the top of the stack.

    Parameters:

      obj (T)

    Return type:

      list[T]

  pop()

    Remove the top item from the stack and return it. If the stack is empty, return `None`.

    Return type:

      T | None

  property top: T | None

    The topmost item on the stack. If the stack is empty, `None` is returned.

  __call__(name=None, *, unbound_message=None)

    Create a `LocalProxy` that accesses the top of this local stack.

    Parameters:

      - name (str | None) – If given, the proxy access this attribute of the top item, rather than the item itself.

      - unbound_message (str | None) – The error message that the proxy will show if the stack is empty.

    Return type:

      LocalProxy[Any]

class werkzeug.local.Local(context_var=None)

  Create a namespace of context-local data. This wraps a `ContextVar` containing a `dict` value.

  This may incur a performance penalty compared to using individual context vars, as it has to copy data to avoid mutating the dict between nested contexts.

  Parameters:

    context_var (ContextVar[dict[str, t.Any]] | None) – The `ContextVar` to use as storage for this local. If not given, one will be created. Context vars not created at the global scope may interfere with garbage collection.

  Changelog

  Changed in version 2.0: Uses `ContextVar` instead of a custom storage implementation.

  __call__(name, *, unbound_message=None)

    Create a `LocalProxy` that access an attribute on this local namespace.

    Parameters:

      - name (str) – Proxy this attribute.

      - unbound_message (str | None) – The error message that the proxy will show if the attribute isn’t set.

    Return type:

      LocalProxy[Any]

# Releasing Data

A previous implementation of `Local` used internal data structures which could not be cleaned up automatically when each context ended. Instead, the following utilities could be used to release the data.

Warning

This should not be needed with the modern implementation, as the data in context vars is automatically managed by Python. It is kept for compatibility for now, but may be removed in the future.

class werkzeug.local.LocalManager(locals=None)

  Manage releasing the data for the current context in one or more `Local` and `LocalStack` objects.

  This should not be needed for modern use cases, and may be removed in the future.

  Parameters:

    locals (None | (Local | LocalStack[t.Any] | t.Iterable[Local | LocalStack[t.Any]])) – A local or list of locals to manage.

  Changelog

  Changed in version 2.1: The `ident_func` was removed.

  Changed in version 0.7: The `ident_func` parameter was added.

  Changed in version 0.6.1: The `release_local()` function can be used instead of a manager.

  cleanup()

    Release the data in the locals for this context. Call this at the end of each request or use `make_middleware()`.

    Return type:

      None

  make_middleware(app)

    Wrap a WSGI application so that local data is released automatically after the response has been sent for a request.

    Parameters:

      app (WSGIApplication)

    Return type:

      WSGIApplication

  middleware(func)

    Like `make_middleware()` but used as a decorator on the WSGI application function.

        @manager.middleware
        def application(environ, start_response):
            ...

    Parameters:

      func (WSGIApplication)

    Return type:

      WSGIApplication

werkzeug.local.release_local(local)

  Release the data for the current context in a `Local` or `LocalStack` without using a `LocalManager`.

  This should not be needed for modern use cases, and may be removed in the future.

  Changelog

  Added in version 0.6.1.

  Parameters:

    local (Local | LocalStack[Any])

  Return type:

    None