Fastapi: StreamResponse of output of several commands

Created on 20 Dec 2020  路  2Comments  路  Source: tiangolo/fastapi

Hello.
I have an API Endpoint:

@app.get("/status", response_model=str)
def status():
    check_one()
    check_two()
    check_three()
    return "done"

What this - right now - actually does is: after all commands are passed, it returns "done".
However, I want to achieve following:

each of the check_XXX-Commands outputs some data (right now via print to the server console). I want this data to be live-stream-returned by the API endpoint to the requestor. This means while requesting the /status-endpoint, it should output only by one:
check_one-outputs ... some time delays ... check_two-outputs ... ... ..

I hope you could understand my idea.
How can this be achieved? I literally have no idea about streaming data, so I am very interested how this can be done!

With best regards,
Martin

question

Most helpful comment

yea, this can be pretty easily done. Make check_one, check_two, check_three yield their output (convert them to generators), you can chain the generators together and return that in a StreamingResponse.

e.g.

import time
from itertools import chain

from fastapi import FastAPI
from fastapi.responses import StreamingResponse


def check_one():
    # check 1
    time.sleep(1)
    yield "passed 1\n"


def check_two():
    # check 2
    time.sleep(1)
    yield "passed 2\n"


def check_three():
    # check 3
    time.sleep(1)
    yield "passed 3\n"


app = FastAPI()


@app.get("/status", response_model=str)
def status():
    gen1 = check_one()
    gen2 = check_two()
    gen3 = check_three()
    return StreamingResponse(chain(gen1, gen2, gen3, ["done"]))

assumed you still wanted "done" in there at the end.

All 2 comments

yea, this can be pretty easily done. Make check_one, check_two, check_three yield their output (convert them to generators), you can chain the generators together and return that in a StreamingResponse.

e.g.

import time
from itertools import chain

from fastapi import FastAPI
from fastapi.responses import StreamingResponse


def check_one():
    # check 1
    time.sleep(1)
    yield "passed 1\n"


def check_two():
    # check 2
    time.sleep(1)
    yield "passed 2\n"


def check_three():
    # check 3
    time.sleep(1)
    yield "passed 3\n"


app = FastAPI()


@app.get("/status", response_model=str)
def status():
    gen1 = check_one()
    gen2 = check_two()
    gen3 = check_three()
    return StreamingResponse(chain(gen1, gen2, gen3, ["done"]))

assumed you still wanted "done" in there at the end.

@falkben Beautiful example 馃槜

@Prutheus JFYK, there's no need for done. Your client you'll know when there's no more body.

Was this page helpful?
0 / 5 - 0 ratings