Локальные переменные контекста
Рано или поздно вам потребуются некоторые вещи, присутствующие в каждом представлении или вспомогательной функции и так далее. В PHP для этого используются глобальные переменные. Однако это невозможно в приложениях WSGI без существенного недостатка: как только вы работаете с глобальным именным пространством, ваше приложение больше не является потокобезопасным.
Стандартная библиотека Python имеет концепцию «локальных переменных потоков» (или данных, локальных для потока). Локальная переменная потока — это глобальный объект, в который вы можете помещать данные и извлекать их позже безопасным и специфичным для потока способом. Это означает, что каждый раз, когда вы устанавливаете или получаете значение в объекте локальной переменной потока, объект проверяет, в каком потоке вы находитесь, и извлекает значение, соответствующее вашему потоку (если оно существует). Таким образом, вы случайно не получите данные другого потока.
Однако этот подход имеет несколько недостатков. Например, помимо потоков, в Python существуют другие типы параллелизма. Очень популярным из них являются greenlet. Также не гарантируется, что каждый запрос получит свой собственный поток в WSGI. Может случиться, что запрос повторно использует поток из предыдущего запроса, и, следовательно, данные остаются в объекте локальной переменной потока.
Werkzeug предоставляет собственную реализацию хранения локальных данных, называемую werkzeug.local. Этот подход обеспечивает функциональность, аналогичную локальным переменным потоков, но также работает с greenlet.
Вот простой пример того, как можно использовать werkzeug.local:
from werkzeug.local import Local, LocalManager
local = Local()
local_manager = LocalManager([local])
def application(environ, start_response):
local.request = request = Request(environ)
...
application = local_manager.make_middleware(application)
Это связывает запрос с local.request. Любой другой фрагмент кода, выполняемый после этого присваивания в том же контексте, может безопасно обращаться к local.request и получит тот же объект запроса. Метод make_middleware в менеджере локальных переменных гарантирует, что все ссылки на локальные объекты будут очищены после запроса.
Один и тот же контекст означает один и тот же greenlet (если вы используете greenlet), один и тот же поток и один и тот же процесс.
Если объект запроса ещё не установлен в локальном объекте, и вы попытаетесь к нему обратиться, вы получите AttributeError. Вы можете использовать getattr чтобы избежать этого:
def get_request():
return getattr(local, 'request', None)
Это попытается получить запрос или вернёт None если запрос ещё не доступен.
Обратите внимание, что локальные объекты не могут управлять собой, для этого вам нужен менеджер локальных переменных. Вы можете передать менеджеру локальных переменных несколько локальных переменных или добавить дополнительные позже, добавив их в manager.locals. Каждый раз, когда менеджер очищает данные, он очищает все данные, оставшиеся в локальных переменных для этого контекста.
-
werkzeug.local.release_local(local) -
Освобождает содержимое локальной переменной для текущего контекста. Это позволяет использовать локальные переменные без менеджера.
Пример:
>>> loc = Local() >>> loc.foo = 42 >>> release_local(loc) >>> hasattr(loc, 'foo') False
С помощью этой функции можно освободить
Localобъекты, а такжеLocalStackобъекты. Однако нельзя таким образом освободить данные, хранящиеся в прокси, так как всегда нужно сохранить ссылку на базовый локальный объект, чтобы иметь возможность освободить его.Изменения
Введено в версии 0.6.1.
- Параметры
-
local (Union[werkzeug.local.Local, werkzeug.local.LocalStack]) –
- Тип возвращаемого значения
-
class werkzeug.local.LocalManager(locals=None, ident_func=None) -
Локальные объекты не могут сами управлять собой. Для этого нужен менеджер локальных переменных. Вы можете передать менеджеру локальных переменных несколько локальных переменных или добавить их позже, добавив их в
manager.locals. Каждый раз, когда менеджер очищает данные, он очищает все данные, оставшиеся в локальных переменных для этого контекста.Изменено в версии 2.0:
ident_funcустарело и будет удалено в Werkzeug 2.1.Изменения
Изменено в версии 0.7: был добавлен параметр
ident_func.Изменено в версии 0.6.1: Вместо менеджера можно использовать функцию
release_local().- Параметры
-
- locals (Optional[Iterable[Union[werkzeug.local.Local, werkzeug.local.LocalStack]]]) –
- ident_func (None) –
- Тип возвращаемого значения
-
cleanup() -
Вручную очищает данные в локальных переменных для данного контекста. Вызовите эту функцию в конце запроса или используйте
make_middleware().- Тип возвращаемого значения
-
get_ident() -
Возвращает идентификатор контекста, который локальные объекты используют внутри этого контекста. Вы не можете переопределить этот метод, чтобы изменить поведение, но можете использовать его для связывания других локальных объектов контекста (например, отсортированных сессий SQLAlchemy) с локальными переменными Werkzeug.
Устарело начиная с версии 2.0: Будет удалено в Werkzeug 2.1.
Изменения
Изменено в версии 0.7: Вы можете передать функцию для определения идентификатора в менеджер локальных переменных, которая затем будет распространена на все локальные переменные, переданные в конструктор.
- Тип возвращаемого значения
-
make_middleware(app) -
Оборачивает WSGI-приложение таким образом, что очистка происходит после завершения запроса.
- Параметры
-
app (WSGIApplication) –
- Тип возвращаемого значения
-
WSGIApplication
-
middleware(func) -
Подобно
make_middleware, но для декорирования функций.Пример использования:
@manager.middleware def application(environ, start_response): ...Различие по сравнению с
make_middlewareзаключается в том, что функция, переданная во внутреннее приложение, будет иметь все аргументы, скопированные от внутреннего приложения (имя, строка документации, модуль).- Параметры
-
func (WSGIApplication) –
- Тип возвращаемого значения
-
WSGIApplication
-
class werkzeug.local.LocalStack -
Этот класс работает аналогично
Local, но хранит стек объектов вместо этого. Это лучше всего объясняется на примере:>>> ls = LocalStack() >>> ls.push(42) >>> ls.top 42 >>> ls.push(23) >>> ls.top 23 >>> ls.pop() 23 >>> ls.top 42
Их можно принудительно освободить, используя
LocalManagerили с помощью функцииrelease_local(), но правильный способ — извлечь элемент из стека после использования. Когда стек пуст, он больше не будет связан с текущим контекстом (и, следовательно, будет освобождён).Вызов стека без аргументов возвращает прокси, который разрешается до самого верхнего элемента в стеке.
Изменения
Введено в версии 0.6.1.
- Тип возвращаемого значения
-
pop() -
Удаляет верхний элемент из стека, вернёт старое значение или
Noneесли стек был пуст.- Тип возвращаемого значения
-
Any
-
push(obj) -
Добавляет новый элемент в стек
- Параметры
-
obj (Any) –
- Тип возвращаемого значения
-
List[Any]
-
property top: Any -
Самый верхний элемент в стеке. Если стек пуст, возвращается
None.
-
class werkzeug.local.LocalProxy(local, name=None) -
Прокси к объекту, привязанному к
Local. Все операции с прокси перенаправляются на связанный объект. Если объект не привязан, генерируетсяRuntimeError.from werkzeug.local import Local l = Local() # a proxy to whatever l.user is set to user = l("user") from werkzeug.local import LocalStack _request_stack = LocalStack() # a proxy to _request_stack.top request = _request_stack() # a proxy to the session attribute of the request proxy session = LocalProxy(lambda: request.session)__repr__и__class__перенаправляются, поэтомуrepr(x)иisinstance(x, cls)будут выглядеть как проксируемый объект. Используйтеissubclass(type(x), LocalProxy)для проверки, является ли объект прокси.repr(user) # <User admin> isinstance(user, User) # True issubclass(type(user), LocalProxy) # True
- Параметры
-
-
local –
Localили вызываемый объект, предоставляющий проксируемый объект. -
name – Имя атрибута для поиска в
Local. Не используется, если задан вызываемый объект.
-
local –
Изменено в версии 2.0: Обновленные проксируемые атрибуты и методы, отражающие текущую модель данных.
Журнал изменений
Изменено в версии 0.6.1: Класс можно инициализировать вызываемым объектом.
-
_get_current_object() -
Возвращает текущий объект. Это полезно, если вам нужен реальный объект за прокси в определенный момент времени для повышения производительности или для передачи объекта в другой контекст.
- Тип возвращаемого значения
-
Любой
© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/2.0.x/local/