(РЕДАКТИРОВАТЬ - gevent.monkey.patch_all () - запускать в файле сценария wsgy.py - автоматически исправляет локальные потоки, чтобы они становились локальными гринлетами, поэтому эта альтернатива с использованием Werkzeug не требуется для GEvent (или GUnicorn с рабочими процессами Gevent) - если каким-то образом вы используете гринлеты без GEvent, вам может понадобиться это решение)
Я нашел себе ответ, вспомнив Flask Framework:
Flask - это платформа, которая поддерживает «глобально» множество объектов, таких как session
и request
, которые «выглядят» как threading.local
объекты. Основное отличие состоит в том, что они являются локальными переменными контекста, а не локальными переменными потока, а контекст - это любой текущий стек выполнения.
У потока есть собственный контекст (отсюда и концепция переключения контекста при чтении о теории потоков). У процесса есть свой контекст, который содержит потоки (и основной поток).
До сих пор в известной нам теории процесс содержит поток, а поток содержит собственный контекст выполнения. Данные всегда являются общими, если поток не может создать свой собственный контекст данных. Здесь появляется концепция локального потока (переменные / данные).
Но для решения этой концепции параллельного выполнения и с учетом проблемы C10K было предпочтительнее асинхронное выполнение в одном потоке вместо нескольких блокирующих потоков с соответствующим переключателем контекста (особенно в отношении python, где у нас есть GIL в python distr0 по умолчанию). Greenlet был создан как контекст переключения одного и того же потока, и теперь иерархия изменилась:
Process 1--* thread 1--* greenlet (and now the requests are here)
Таким образом, концепция Greenlets была создана и реализована в Python на серверах, таких как Gevent, и вы больше не можете использовать локальные данные потока, потому что запросы больше не привязаны к потокам (т.е. они могут совместно использовать один и тот же локальный контекст потока. , скачок над данными).
Теперь сам контекст является гринлетом, и нам нужно понятие локального контекста, а не локальных переменных потока.
Итак: как Flask использует локальный контекст, который изолирует данные для каждого запроса? (например, сеанс, запрос). Ответ на контекстно-независимую изоляцию находится здесь:
Контекстные локальные переменные Werkzeug
Создатель Werkzeug и Flask один и тот же. Werkzeug - это не фреймворк, а просто набор утилит, которые вы можете использовать в любой структуре WSGI (например, Django). Сама структура - это Flask, которая фактически зависит от утилит Werkzeug.
Локальные переменные контекста Werkzeug помогают создавать (правильно сказано) локальные переменные контекста (контекст, означающий либо поток, запрос или процесс - в зависимости от того, как сервер отправляет запросы), которые могут помочь нам хранить данные, относящиеся к гринлету, и избегать использования threadlocals:
#a python module for my django project where I define
#a custom field class which statically needs to know the
#current request.
#I was using, instead, a threadlocal. The usage is THE SAME.
#the main difference is that threads are GCed, while contexts
#not necessarily, so you must ALWAYS release them explicitly
#using release_local, for the current context.
#this code below used to have `threading.local` instances
#instead of `werkzeug.local.Local` instances.
#as I said before, assigning data works like before, but
#the main difference is when releasing the data.
from werkzeug.local import Local, release_local
class AutocompleteField(object):
DATA = Local()
@staticmethod
def set_request(request):
AutocompleteField.DATA.request = request
@staticmethod
def unset_request(request):
release_local(AutocompleteField.DATA)
@staticmethod
def get_request():
try:
return AutocompleteField.DATA.request
except AttributeError as e:
return None
person
Community
schedule
16.07.2014