Экземпляры и объекты приложений PEP 333

Недавно я пытался узнать о WSGI и, кроме того, о том, как работает сеть в отношении Python. Поэтому я читал Werkzeug и PEP333, чтобы учиться.

Однако я столкнулся с небольшим вопросом, который, я думаю, понимаю, но, вероятно, нет, поэтому я был бы признателен за то, что вы направили его в правильном направлении.

PEP333 утверждает:

Объект приложения — это просто вызываемый объект, который принимает два аргумента. Термин "объект" не следует истолковывать как требующий фактического экземпляра объекта: функция, метод, класс или экземпляр с методом вызова приемлемы для использования в качестве объекта приложения. Объекты приложений должны иметь возможность вызываться более одного раза, поскольку практически все серверы/шлюзы (кроме CGI) будут делать такие повторяющиеся запросы.

Реализация:

class AppClass:
    """Produce the same output, but using a class

    (Note: 'AppClass' is the "application" here, so calling it
    returns an instance of 'AppClass', which is then the iterable
    return value of the "application callable" as required by
    the spec.

    If we wanted to use *instances* of 'AppClass' as application
    objects instead, we would have to implement a '__call__'
    method, which would be invoked to execute the application,
    and we would need to create an instance for use by the
    server or gateway.
    """

    def __init__(self, environ, start_response):
        self.environ = environ
        self.start = start_response

    def __iter__(self):
        status = '200 OK'
        response_headers = [('Content-type', 'text/plain')]
        self.start(status, response_headers)
        yield "Hello world!\n"

Мой вопрос здесь только для того, чтобы уточнить, правильно ли я понял это.

В нем указано, что AppClass — это приложение, и когда мы его вызываем, оно возвращает экземпляр AppClass. Но затем дальше говорится, что «если мы хотим вместо этого использовать экземпляры объектов приложения AppClass as», значит ли это, что когда серверная сторона WSGI вызывает объект AppClass, работает только один экземпляр?

Например. Сервер может отправить несколько запросов (200 OK) к приложению для получения дополнительных ответов, поэтому iter помещается в класс. Но каждый запрос проходит через один и тот же единственный экземпляр AppClass, каждый запрос к серверу в основном не создает более одного экземпляра AppClass?

Извините, если это многословно, и еще раз извиняюсь, если я не имел большого смысла. Я пытаюсь улучшить atm.

Ценим ваш вклад, как всегда.

Спасибо.


person John Von Neumann    schedule 16.07.2017    source источник
comment
Серверная технология создаст AppClass для каждого запроса (поскольку каждый запрос будет иметь потенциально уникальный environ)   -  person Anthony Sottile    schedule 17.07.2017
comment
Кстати, я бы также посоветовал прочитать PEP3333 (обновленная версия PEP333 )   -  person Anthony Sottile    schedule 17.07.2017
comment
Приветствую человека! Я думаю, что это имеет немного больше смысла, я намерен перейти на PEP 3333 после того, как немного разберусь с PEP333, или вы рекомендуете двигаться дальше сейчас, потому что это более актуально?   -  person John Von Neumann    schedule 17.07.2017
comment
На самом деле, теперь, когда я думаю об этом, это имеет большой смысл, когда передается environ dict, и это, очевидно, должно быть уникальным из-за того, что оно поступает от запрашивающих.   -  person John Von Neumann    schedule 17.07.2017
comment
уточню в ответе   -  person Anthony Sottile    schedule 17.07.2017


Ответы (2)


Серверная технология будет вызывать ваш app (в данном случае класс AppClass, вызывающий создание объекта) для каждого запроса. Это связано с тем, что каждый запрос будет иметь потенциально уникальный environ.

Самое интересное в этом то, что это не означает, что ваш app должен быть классом, я часто нахожу полезным определить мое приложение wsgi (или промежуточное ПО) как функцию, возвращающую функцию:

# I'd strongly suggest using a web framework instead to define your application
def my_application(environ, start_response):
    start_response(str('200 OK'), [(str('Content-Type'), str('text/plain'))])
    return [b'hello world!\n']

def my_middleware(app):
    def middleware_func(environ, start_response):
        # do something or call the inner app
        return app(environ, start_response)
    return middleware_func

# expose `app` for whatever server tech you're using (such as uwsgi)
app = my_application
app = my_middleware(app)

Другой распространенный шаблон включает определение объекта для хранения некоторого состояния приложения, которое создается один раз:

class MyApplication(object):
    def __init__(self):
        # potentially some expensive initialization
        self.routes = ...

    def __call__(self, environ, start_response):
        # Called once per request, must call `start_response` and then
        # return something iterable -- could even be `return self` if
        # this class were to define `__iter__`
        ...
        return [...]

app = MyApplication(...)

Что касается PEP333, я бы посоветовал вместо этого прочитать PEP3333 -- он содержит в основном та же информация, но уточняются типы данных, используемые повсюду.

person Anthony Sottile    schedule 16.07.2017

Для получения дополнительной информации о различных способах реализации объектов приложения WSGI прочитайте эту запись в блоге на эту тему.

Я бы также посоветовал прочитать следующее, в котором рассказывается о том, как в целом работают веб-серверы Python.

Если у вас действительно нет необходимости, вы, вероятно, просто хотите использовать фреймворк. Не пытайтесь писать что-либо с нуля с помощью WSGI.

person Graham Dumpleton    schedule 17.07.2017
comment
Я действительно наткнулся на ваши блоги в своих путешествиях за информацией, ха-ха. Я нашел их полезными. Я намерен использовать фреймворк для всей своей работы, мне просто не нравится использовать вещи, которых я не понимаю, это всегда лень. - person John Von Neumann; 17.07.2017