Spec-Zone.ru › Werkzeug 1.0

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

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

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

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

Spec-Zone.ru

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