Локальные переменные контекста
Рано или поздно вам понадобятся некоторые вещи, которые вы хотите иметь в каждом представлении или вспомогательной функции и так далее. В PHP для этого используются глобальные переменные. Однако в приложениях WSGI это невозможно без существенного недостатка: как только вы работаете с глобальным пространством имен, ваше приложение больше не является потокобезопасным.
Стандартная библиотека Python имеет концепцию «потоковых локалей» (или данных потоков). Потоковая локаль — это глобальный объект, в который вы можете поместить данные и получить их позже безопасным и специфичным для потока способом. Это означает, что всякий раз, когда вы устанавливаете или получаете значение в потоковой локали, потоковая локаль проверяет, в каком потоке вы находитесь, и извлекает значение, соответствующее вашему потоку (если оно существует). Таким образом, вы случайно не получите данные другого потока.
Однако этот подход имеет несколько недостатков. Например, помимо потоков, в Python есть и другие типы конкурентности. Очень популярным является greenlets. Также не гарантируется, что каждый запрос получит свой собственный поток в WSGI. Возможен случай, когда запрос повторно использует поток из предыдущего запроса, и, следовательно, данные остаются в объекте потоковой локали.
Werkzeug предоставляет собственное реализацию хранения локальных данных под названием werkzeug.local. Этот подход обеспечивает функциональность, аналогичную потоковым локалям, но также работает с greenlets.
Вот простой пример того, как можно использовать 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 (если вы используете greenlets) в том же потоке и том же процессе.
Если объект запроса еще не установлен в локальном объекте, и вы пытаетесь получить к нему доступ, вы получите 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.
-
class werkzeug.local.LocalManager(locals=None, ident_func=None) -
Локальные объекты не могут управлять собой. Для этого нужен локальный менеджер. Вы можете передать локальному менеджеру несколько локалей или добавить их позже, добавив их в
manager.locals. Каждый раз, когда менеджер очищает данные, он очистит все данные, оставшиеся в локалях для этого контекста.Параметр
ident_funcможет быть добавлен для переопределения функции ident по умолчанию для обернутых локалей.Изменено в версии 0.6.1: Вместо менеджера можно использовать функцию
release_local().Изменено в версии 0.7:
ident_funcбыл добавлен.-
cleanup() -
Вручную очищает данные в локалях для этого контекста. Вызовите это в конце запроса или используйте
make_middleware().
-
get_ident() -
Возвращает идентификатор контекста, который локальные объекты используют внутри для этого контекста. Вы не можете переопределить этот метод для изменения поведения, но используйте его для связи других локальных объектов контекста (например, ссылочных сессий SQLAlchemy) с локалями Werkzeug.
Изменено в версии 0.7: Вы можете передать другую функцию ident в локальный менеджер, которая затем будет передана всем локалям, переданным в конструктор.
-
make_middleware(app) -
Оборачивает приложение WSGI, чтобы очистка происходила после завершения запроса.
-
middleware(func) -
Как
make_middlewareно для декорирования функций.Пример использования:
@manager.middleware def application(environ, start_response): ...Разница с
make_middlewareзаключается в том, что функция, переданная в этот метод, будет иметь все аргументы скопированы из внутреннего приложения (имя, строка документации, модуль).
-
-
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если стек был пуст.
-
push(obj) -
Добавляет новый элемент в стек
-
top -
Самый верхний элемент стека. Если стек пуст, возвращается
None.
-
-
class werkzeug.local.LocalProxy(local, name=None) -
Выступает в качестве прокси для локальной переменной Werkzeug. Перенаправляет все операции на проксируемый объект. Единственные операции, не поддерживаемые для перенаправления, — это правые операнды и любые типы присваивания.
Пример использования:
from werkzeug.local import Local l = Local() # these are proxies request = l('request') user = l('user') from werkzeug.local import LocalStack _response_local = LocalStack() # this is a proxy response = _response_local()Всякий раз, когда что-то привязывается к l.user / l.request, объекты прокси будут перенаправлять все операции. Если объект не привязан, будет возбуждено исключение
RuntimeError.Для создания прокси к
LocalилиLocalStackобъектам, вызовите объект, как показано выше. Если вы хотите иметь прокси к объекту, ищущему по функции, вы можете (с версии Werkzeug 0.6.1) передать функцию в конструкторLocalProxy:session = LocalProxy(lambda: get_current_request().session)
Изменено в версии 0.6.1: Теперь класс можно инициализировать вызываемым объектом.
Обратите внимание, что
repr()также перенаправляется, поэтому если вы хотите узнать, имеете ли вы дело с прокси, вы можете выполнить проверкуisinstance():>>> from werkzeug.local import LocalProxy >>> isinstance(request, LocalProxy) True
Вы также можете создать объекты прокси вручную:
from werkzeug.local import Local, LocalProxy local = Local() request = LocalProxy(local, 'request')
-
_get_current_object() -
Возвращает текущий объект. Это полезно, если вы хотите получить реальный объект за прокси в определенное время по причинам производительности или потому что вы хотите передать объект в другой контекст.
-
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/0.16.x/local/