问题 WSGI:start_response函数的目的是什么


你能提供一个真实的例子吗? WSGI  start_response 功能? (Web服务器为wsgi应用程序提供该功能)

我无法理解 目的 介绍 start_response

(我读过10个关于WSGI标准的相同文本。他们都说“WSGI标准是......”他们都没有说“WSGI是这样设计的” 为了......“:()


3905
2018-05-27 14:05


起源



答案:


你能提供一个真实的WSGI例子吗? start_response() 功能?

好吧, start_response() 功能 mod_wsgi 定义于 第2678行 mod_wgsi.c

他们都没有说“WSGI就是这样设计的......”

对于WSGI设计的这一方面似乎没有多少理由 PEP3333。透过 web-sig邮件列表档案, 我碰到 这条信息...

前段时间我反对删除start_response的决定   来自下一版本WSGI的功能,使用的理由是   没有start_callable,异步扩展是不可能的   支持。

现在我发现删除start_response也会   不可能支持协程(或者至少是一些协程   用法)。

[...]

...开始了一个关于这部分实施的理由的长篇大论,这可能值得一读。

如果你真的想知道WSGI接口这方面的起源,你将不得不阅读很多消息 这个初稿 2003年12月,和 这个后来的选秀 在2004年8月。


更新

如何与其他协议兼容?

我不太清楚你的意思。忽略所有早期草案,WSGI 1.x界面可以以两种不同的方式使用。

“弃用”方法是......

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    write('content block 2')
    write('content block 3')
    return None

......而'推荐'的方法是......

def application(environ, start_response):
    start_response(status, headers)
    return ['content block 1',
            'content block 2',
            'content block 3']

据推测,你可以使用两者,...

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    return ['content block 2',
            'content block 3']

...但结果行为可能未定义。

由外观 这篇博文,正在考虑的新WSGI 2.x方法是......

def application(environ):
    return (status,
            headers,
            ['content block 1',
             'content block 2',
             'content block 3'])

......这消除了 start_response() 可赎回的,显然是 write() 可以调用,但没有迹象表明何时(或者甚至是否)这可能会取代WSGI 1.x.


9
2018-05-27 14:53



请不要让异步支持者在start_response()的范围内混淆水域。其中一个主要原因是允许服务器返回write()可调用以支持现有的Python Web应用程序,这些应用程序曾用于调用write()函数来生成内容。这使他们免于被重写以返回可迭代。 - Graham Dumpleton
@GrahamDumpleton嗯,鉴于我没有参与设计过程,我也不会费心阅读web-sig档案中的每一条消息,我真的只能推测。但是,似乎我将初始草案链接到了提议使用函数 def runCGI(input,output,errors,environ),也会提供这样一个可调用的via output.write()。看起来更像是有人反对Web应用程序必须手动编写 HTTP/1.1 200 OK line,以及响应标头本身。 - Aya
我也不在那里,你挖出了我以前从未读过的东西。 runCGI版本在更改为返回可迭代之前就已存在,因此输出完全通过write()。他们可能已经抛弃了write(),这就是WSGI 2+解决方案最终提出的建议。在不需要write()的WSGI 2+中,start_response()也消失了。不再需要挂起write(),因为依赖于能够执行write()的非常旧的应用程序不再存在或者已经被重写,现在返回响应的可迭代。 - Graham Dumpleton
@GrahamDumpleton,@ Aya首先,谢谢你们有用的链接和人类可读的解释。奇怪的是,在返回的链接页面中没有示例 write 函数可以由应用程序使用。是真的,一个与WSGI和其他网关协议兼容的应用程序应该如下使用它: write = start_response(status,headers); write(data)? - Boris Burkov
@GrahamDumpleton,@ Aya如何与其他协议兼容?我想,隐含的其他协议只会将应用程序称为 application(environ, start_response=gateway_write),提供其定制 gateway_write 应用程序的输入功能?然后应用程序应该直接调用 start_response(data) 代替 write = start_response(status,headers); write(data) 和WSGI与其他协议不兼容? - Boris Burkov


答案:


你能提供一个真实的WSGI例子吗? start_response() 功能?

好吧, start_response() 功能 mod_wsgi 定义于 第2678行 mod_wgsi.c

他们都没有说“WSGI就是这样设计的......”

对于WSGI设计的这一方面似乎没有多少理由 PEP3333。透过 web-sig邮件列表档案, 我碰到 这条信息...

前段时间我反对删除start_response的决定   来自下一版本WSGI的功能,使用的理由是   没有start_callable,异步扩展是不可能的   支持。

现在我发现删除start_response也会   不可能支持协程(或者至少是一些协程   用法)。

[...]

...开始了一个关于这部分实施的理由的长篇大论,这可能值得一读。

如果你真的想知道WSGI接口这方面的起源,你将不得不阅读很多消息 这个初稿 2003年12月,和 这个后来的选秀 在2004年8月。


更新

如何与其他协议兼容?

我不太清楚你的意思。忽略所有早期草案,WSGI 1.x界面可以以两种不同的方式使用。

“弃用”方法是......

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    write('content block 2')
    write('content block 3')
    return None

......而'推荐'的方法是......

def application(environ, start_response):
    start_response(status, headers)
    return ['content block 1',
            'content block 2',
            'content block 3']

据推测,你可以使用两者,...

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    return ['content block 2',
            'content block 3']

...但结果行为可能未定义。

由外观 这篇博文,正在考虑的新WSGI 2.x方法是......

def application(environ):
    return (status,
            headers,
            ['content block 1',
             'content block 2',
             'content block 3'])

......这消除了 start_response() 可赎回的,显然是 write() 可以调用,但没有迹象表明何时(或者甚至是否)这可能会取代WSGI 1.x.


9
2018-05-27 14:53



请不要让异步支持者在start_response()的范围内混淆水域。其中一个主要原因是允许服务器返回write()可调用以支持现有的Python Web应用程序,这些应用程序曾用于调用write()函数来生成内容。这使他们免于被重写以返回可迭代。 - Graham Dumpleton
@GrahamDumpleton嗯,鉴于我没有参与设计过程,我也不会费心阅读web-sig档案中的每一条消息,我真的只能推测。但是,似乎我将初始草案链接到了提议使用函数 def runCGI(input,output,errors,environ),也会提供这样一个可调用的via output.write()。看起来更像是有人反对Web应用程序必须手动编写 HTTP/1.1 200 OK line,以及响应标头本身。 - Aya
我也不在那里,你挖出了我以前从未读过的东西。 runCGI版本在更改为返回可迭代之前就已存在,因此输出完全通过write()。他们可能已经抛弃了write(),这就是WSGI 2+解决方案最终提出的建议。在不需要write()的WSGI 2+中,start_response()也消失了。不再需要挂起write(),因为依赖于能够执行write()的非常旧的应用程序不再存在或者已经被重写,现在返回响应的可迭代。 - Graham Dumpleton
@GrahamDumpleton,@ Aya首先,谢谢你们有用的链接和人类可读的解释。奇怪的是,在返回的链接页面中没有示例 write 函数可以由应用程序使用。是真的,一个与WSGI和其他网关协议兼容的应用程序应该如下使用它: write = start_response(status,headers); write(data)? - Boris Burkov
@GrahamDumpleton,@ Aya如何与其他协议兼容?我想,隐含的其他协议只会将应用程序称为 application(environ, start_response=gateway_write),提供其定制 gateway_write 应用程序的输入功能?然后应用程序应该直接调用 start_response(data) 代替 write = start_response(status,headers); write(data) 和WSGI与其他协议不兼容? - Boris Burkov


我发现一个旧线程可以解释原因。

为什么有start_response然后单独返回?

一个原因是它允许您将应用程序编写为生成器。但更重要的是,为了支持'write()'以便与现有框架向后兼容,这是必要的,而这几乎是它的结构化的“杀手锏”。这个特别的创新是Tony Lownds的心血结晶,但不是我的。在我最初的WSGI概念中,应用程序收到了一个输出流,只是编写了标题和所有内容。


2
2018-06-19 02:32