Python Flask + nginx fcgi-вывод большого отклика?

Я использую 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 (вероятно, каким-то потоком).

Я не смог найти решение этой, казалось бы, распространенная проблема. Как этого добиться?

спасибо!

1 ответов


если response на flask.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()

если вы запустите этот и попробовать его в браузере, вы должны увидеть хороший incemental рассчитывать...

(тип контента не задан, потому что кажется, что если я это сделаю, мой браузер ждет, пока весь контент не будет перед отображением страницы. wget -qO - localhost:5000 не имеет этих проблем.