Локальные переменные контекста
В какой-то момент вам потребуются данные, доступные во всех представлениях или вспомогательных функциях. В 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.
- Параметры
-
local (Union[werkzeug.local.Local, werkzeug.local.LocalStack]) –
- Тип возвращаемого значения
-
None
-
class werkzeug.local.LocalManager(locals=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]]]) –
- Тип возвращаемого значения
-
None
-
cleanup() -
Вручную очистите данные в локальных переменных для этого контекста. Вызовите эту функцию в конце обработки запроса или используйте
make_middleware().- Тип возвращаемого значения
-
None
-
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.
- Тип возвращаемого значения
-
None
-
pop() -
Удаляет самый верхний элемент из стека, возвращает старое значение или
Noneесли стек был уже пуст.- Тип возвращаемого значения
-
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–2022 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/2.1.x/local/