6

我将 Python Flask + nginx 与 FCGI 一起使用。

在某些请求中,我必须输出大量响应。通常这些响应是从套接字中获取的。目前我正在做这样的回应:

response = []
while True:
    recv = s.recv(1024)
    if not recv: break
    response.append(recv)
s.close()
response = ''.join(response)

return flask.make_response(response, 200, {
                                           'Content-type': 'binary/octet-stream',
                                           'Content-length': len(response),
                                           'Content-transfer-encoding': 'binary',
                                           })

问题是我实际上不需要数据。我还有一种方法可以确定要从套接字获取的确切响应长度。所以我需要一种发送 HTTP 标头的好方法,然后直接从套接字开始输出,而不是在内存中收集它然后提供给 nginx(可能通过某种流)。

我无法找到这个看似常见问题的解决方案。那将如何实现?

谢谢!

4

1 回答 1

10

如果responseinflask.make_response是可迭代的,则将对其进行迭代以产生响应,并且每个字符串都将自己写入输出流。

这意味着您还可以返回一个生成器,该生成器将在迭代时产生输出。如果您知道内容长度,那么您可以(并且应该)将其作为标题传递。

一个简单的例子:

from flask import Flask
app = Flask(__name__)
import sys
import time
import flask

@app.route('/')
def generated_response_example():
    n = 20
    def response_generator():
        for i in range(n):
            print >>sys.stderr, i
            yield "%03d\n" % i
            time.sleep(.2)

    print >>sys.stderr, "returning generator..."
    gen = response_generator()

    # the call to flask.make_response is not really needed as it happens imlicitly 
    # if you return a tuple.
    return flask.make_response(gen ,"200 OK", {'Content-length': 4*n})

if __name__ == '__main__':
    app.run()

如果您运行它并在浏览器中尝试,您应该会看到一个不错的初始计数...

(内容类型未设置,因为如果我这样做,我的浏览器似乎会等到整个内容在呈现页面之前被流式传输。wget -qO - localhost:5000没有这个问题。

于 2012-05-18T11:58:26.050 回答