串流內容¶
有時候您會想要傳送大量的資料給客戶端,遠遠超出您想要保存在記憶體中的資料量。當您在動態產生資料時,如何在不經過往返檔案系統的情況下將資料傳回給客戶端呢?
答案是使用生成器和直接回應。
基本用法¶
這是一個基本視圖函式,可以動態產生大量的 CSV 資料。訣竅是擁有一個內部函式,該函式使用生成器來產生資料,然後調用該函式並將其傳遞給回應物件
@app.route('/large.csv')
def generate_large_csv():
def generate():
for row in iter_all_rows():
yield f"{','.join(row)}\n"
return generate(), {"Content-Type": "text/csv"}
每個 yield
表達式都會直接傳送到瀏覽器。但請注意,某些 WSGI 中介軟體可能會中斷串流,因此在啟用分析器和其他功能的偵錯環境中要小心。
從範本串流¶
Jinja2 範本引擎支援逐片渲染範本,並傳回字串的迭代器。Flask 提供了 stream_template()
和 stream_template_string()
函式,使這更容易使用。
from flask import stream_template
@app.get("/timeline")
def timeline():
return stream_template("timeline.html")
渲染串流產生的部分往往與範本中的語句塊匹配。
使用上下文串流¶
當生成器正在執行時,request
將不會處於活動狀態,因為視圖在那時已經返回。如果您嘗試存取 request
,您將會收到 RuntimeError
。
如果您的生成器函式依賴於 request
中的資料,請使用 stream_with_context()
包裝器。這將使請求上下文在生成器執行期間保持活動狀態。
from flask import stream_with_context, request
from markupsafe import escape
@app.route('/stream')
def streamed_response():
def generate():
yield '<p>Hello '
yield escape(request.args['name'])
yield '!</p>'
return stream_with_context(generate())
它也可以用作裝飾器。
@stream_with_context
def generate():
...
return generate()
如果請求處於活動狀態,stream_template()
和 stream_template_string()
函式會自動使用 stream_with_context()
。