Spec-Zone.ru › Werkzeug 0.15

Локальные переменные контекста

Рано или поздно вам понадобятся некоторые вещи, которые должны присутствовать в каждом представлении или вспомогательной функции и т.д. В 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 можно добавить, чтобы переопределить функцию идентификации по умолчанию для обернутых локальных переменных.

Изменено в версии 0.6.1: Вместо менеджера также можно использовать функцию release_local().

Изменено в версии 0.7: ident_func был добавлен.

cleanup()

Вручную очистите данные в локальных переменных для этого контекста. Вызовите эту функцию в конце обработки запроса или используйте make_middleware().

get_ident()

Возвращает идентификатор контекста, который локальные объекты используют внутри для этого контекста. Вы не можете переопределить этот метод, чтобы изменить поведение, но используйте его для связи других локальных объектов контекста (например, отмасштабированных сессий SQLAlchemy) с локальными переменными Werkzeug.

Изменено в версии 0.7: Вы можете передать менеджеру локальных переменных другую функцию идентификации, которая затем будет распространена на все локальные переменные, переданные в конструктор.

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.15.x/local/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API