Короткий ответ
Данные кладут в объект flask.g, который привязан к текущему request context и автоматически пересоздаётся для каждого нового запроса — это потокобезопасно, так как каждый поток/greenlet обрабатывает свой собственный контекст.
Как это работает подробнее
Flask использует механизм контекстных локальных переменных (context locals, основанных на werkzeug.local/contextvars), который хранит отдельный g для каждого активного request context. Даже если сервер обрабатывает несколько запросов параллельно в разных потоках, каждый поток видит «свой» g, а не общий для всех.
Пример кода
example.py
from flask import Flask, g, request
app = Flask(__name__)
@app.before_request
def load_current_user():
token = request.headers.get("X-Token")
g.current_user = {"id": 1, "name": "Alice"} if token else None
@app.route("/profile")
def profile():
if g.current_user is None:
return {"error": "unauthorized"}, 401
return g.current_user
# Параллельные запросы с разными заголовками X-Token друг на друга не влияют,
# т.к. g пересоздаётся для каждого запроса в своём контексте.Что использовать на практике
- Практика.
before_requestобычно используют для подготовки данных, нужных нескольким view (например, текущий пользователь из токена), и сохраняют результат вg.current_user; после обработки запросаgавтоматически уничтожается, так что данные не «утекают» в следующий запрос.
Подводные камни
- Риск. Пытаются хранить в
gданные, которые должны жить дольше одного запроса (например, кэш между запросами) — для этогоgне подходит, нужен внешний кэш; обращаются кg.current_userв коде, который может выполняться вне активного request context (например, в фоновом потоке), получаяRuntimeError: Working outside of request context.