PEP 333 应用程序实例和对象

PEP 333 Application Instances and Objects

我最近一直在尝试学习 WSGI 以及网络在 Python 方面的工作方式。所以我一直在阅读 Werkzeug 和 PEP333 来学习。

但是我 运行 遇到了一个小问题,我认为我理解但可能不理解,所以我很感激你指导正确的方向。

PEP333 指出:

The application object is simply a callable object that accepts two arguments. The term "object" should not be misconstrued as requiring an actual object instance: a function, method, class, or instance with a call method are all acceptable for use as an application object. Application objects must be able to be invoked more than once, as virtually all servers/gateways (other than CGI) will make such repeated requests.

实施:

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是应用程序,当我们调用它时,它returns是AppClass的一个实例。但是再往下说'if we wanted to use instances of AppClass ass application objects instead',这是不是说WSGI的server端调用AppClass对象时,只有一个实例运行ning?

例如。服务器可以向应用程序发出多个请求(200 OK)以获得更多响应,因此 iter 被放入 class。但是每个请求 运行s 通过同一个单一的 AppClass 实例,每个对服务器的请求基本上不会实例化一个以上的 AppClass 实例?

对不起,如果这是冗长的话,如果我没有说清楚,请再次道歉。我正在努力改进 atm。

一如既往地感谢您的意见。

谢谢。

服务器技术将为每个请求调用您的app(在本例中为classAppClass,导致对象构造) .这是因为每个请求都可能具有唯一的 environ.

巧妙的是,这并不意味着您的 app 必须是 class,我经常发现将我的 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——它包含的信息大致相同,但阐明了贯穿始终的数据类型。

有关实现 WSGI 应用程序对象的各种方式的背景,请阅读有关该主题的博客post。

我还建议阅读以下内容,其中讨论了 Python Web 服务器的一般工作方式。

除非你真的有需要,否则你可能只想使用一个框架。避免尝试使用 WSGI 从头开始​​编写任何东西。