6

私はFCGIでPythonFlask+nginxを使用しています。

一部のリクエストでは、大きな応答を出力する必要があります。通常、これらの応答はソケットからフェッチされます。現在、私は次のような応答を行っています。

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が iterable の場合、反復処理されて応答が生成され、各文字列が単独で出力ストリームに書き込まれます。

これが意味することは、反復したときに出力を生成するジェネレーターを返すこともできるということです。コンテンツの長さがわかっている場合は、それをヘッダーとして渡すことができます (そして渡す必要があります)。

簡単な例:

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 に答える