3

我最近一直在尝试学习 WSGI 以及 Web 与 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 ass 应用程序对象的实例来代替”,这是否是说当 WSGI 的服务器端调用 AppClass 对象时,只有一个实例在运行?

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

对不起,如果这是冗长的,如果我没有多大意义,再次道歉。我正在努力改进atm。

一如既往地感谢您的投入。

谢谢。

4

2 回答 2

1

服务器技术将为每个请求调用您的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——它包含大致相同的信息,但阐明了自始至终使用的数据类型。

于 2017-07-16T22:57:41.403 回答
1

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

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

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

于 2017-07-17T02:11:35.020 回答