Подтвердить что ты не робот

Понимание сохранения глобального объекта в приложениях WSGI Python

Рассмотрим следующий код в приложении WebApp2 в Google App Engine:

count = 0

class MyHandler(webapp2.RequestHandler):

    def get(self):

        global count
        count = count + 1
        print count

При каждом обновлении страницы количество увеличивается.

Я иду из мира PHP, где каждый запрос был новой глобальной средой. Я понимаю, что здесь происходит, потому что я использую конфигурацию wsgi для WebApp2, Python не запускает новый процесс для каждого запроса. Если бы я использовал конфигурацию cgi, с другой стороны, глобальная среда будет повторно создавать экземпляры каждый раз, например PHP...

Предполагая, что это правильно (если нет, пожалуйста, исправьте меня)...

  • Как я могу обрабатывать сценарии, где мне нужна глобальная переменная, которая сохраняется только для срока службы запроса? Я могу поместить переменную экземпляра в класс RequestHandler, но как насчет таких вещей, как модули утилиты, которые я импортирую, которые используют глобальные вары для таких вещей, как сохранение объекта сообщения?
  • Есть ли какой-либо метод для reset всех переменных или принудительное повторное создание среды?
  • Сохраняется ли глобальная среда неопределенно долго или сама она reset в какой-то момент?
  • Является ли какой-либо из этих GAE конкретным, или глобальное сопротивление wsgi работает одинаково в любом сценарии сервера?

EDIT:

Здесь попытка использования threadlocal:

count = 0

mydata = threading.local()
mydata.count = 0

class MyHandler(webapp2.RequestHandler):

    def get(self):

        global count
        count = count + 1
        print count

        mydata.count = mydata.count + 1
        print mydata.count

Они также увеличивают количество запросов

4b9b3361

Ответ 1

Ваше понимание верное. Если вы хотите, чтобы переменные сохранялись в течение всего срока действия запроса, вы не должны делать их глобальными, - сделайте им переменные экземпляра в вашем классе RequestHandler, доступ к которому можно получить как self.var. Поскольку для каждого запроса создается новый RequestHandler, ваши переменные будут придерживаться точно столько, сколько вам нужно. Глобальные переменные лучше избегать, если вам действительно не нужна глобальная (в отличие от специфичной для запроса) область.

Также обратите внимание, что приложение App Engine будет работать на нескольких серверах; globals доступны только для запросов внутри одного и того же сервера.

Ответ 2

Ваш анализ ситуации верен, веб-приложение Python - это долговременный процесс. Это займет много времени, чтобы развернуть интерпретатор Python и не выполняется каждый запрос.

Полностью можно создать глобальную переменную, которая отличается "по запросу". Это делается во многих рамках, и людям это нравится. Способ сделать это зависит от сервера. Большинство серверов используют "один поток для каждого запроса", и я думаю, что GAE также работает. Если это так, вы можете использовать threadlocal variable. Если вы обеспокоены тем, что это значение существует между запросами в этом потоке, вам понадобится код управления, который может подключиться к началу/концу запроса. Связующее ПО WSGI является хорошим местом для этого, если инфраструктура WebApp2 не обеспечивает хороший способ сделать это.

Это просто Python, и запрос подается в его собственном потоке. Оттуда вы можете делать то, что хотите. В Python нет ничего, кроме всего reset всех глобальных переменных, и обычно нет гарантии (особенно с GAE), что процесс, обслуживающий ваш запрос, будет таким же процессом каждый раз, что означает, что ваши глобальные значения не должны использоваться для сохранения данных между запросами если вы действительно не знаете, что делаете.

Есть много фреймворков, которые обеспечивают хорошую поддержку для этого, поэтому, если WebApp2 не сделает этого, я предлагаю искать в другом месте. Python имеет множество опций, и многие из них работают на GAE.

Ответ 3

В случае вашего первого вопроса, я думаю, вы можете рассмотреть функцию webapp2.Request.registry. Это диктофон для хранения экземпляров, которые могут использовать разные модули в течение всего срока службы запроса.

С другой стороны, полезно также webapp2.WSGIApplication.registry. В этом случае экземпляры сохраняются между запросами и могут совместно использоваться (и повторно использоваться) для любого приложения, которое требуется в течение всего срока службы вашего приложения, избегая создания экземпляров в глобальной области.