8

No code here, just a question. I have tried various means to get a streamlit app to run within a flask app. Main reason? Using Flask for user authentication into the streamlit app. Cannot get it to work out. Is it not possible perhaps?

John Taylor
  • 655
  • 6
  • 19

2 Answers2

10

Streamlit uses Tornado to serve HTTP and WebSocket data to its frontend. That is, it’s already its own web server, and is written in an existing web framework; it wouldn’t be trivial to wrap it inside another web framework.

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.

Flask is a synchronous web framework and not ideal for WebSockets etc.

Serving an interactive Streamlit app via flask.render_template isn’t feasible, because Streamlit apps are not static; when you interact with your Streamlit app, it is re-running your Python code to generate new results dynamically

Follow these discussions for more info

Ailurophile
  • 2,552
  • 7
  • 21
  • 46
0


import asyncio
import subprocess

from mlflow.server import app as mlflow_app

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.wsgi import WSGIMiddleware
import uvicorn
from fastapi.logger import logger
import uuid
from config import *

streamlit_app_process = None
streamlit_app_stdout = None
streamlit_app_stderr = None


async def registry_subprocess() -> None:
    logger.debug("registry distance_matrix")
    global streamlit_app_process
    global streamlit_app_stdout
    global streamlit_app_stderr
    id = str(uuid.uuid1())
    streamlit_app_stdout = open(f"/tmp/subprocess_stdout_{''.join(id.split('-'))}", 'w+b')
    streamlit_app_stderr = open(f"/tmp/subprocess_stderr_{''.join(id.split('-'))}", 'w+b')
    cmd = ['streamlit', 'run', f'{app_dir}/Home.py', f'--server.port={streamlit_app_port}', f'--server.address={streamlit_app_host}']
    logger.info(f"subprocess start cmd {cmd}")
    streamlit_app_process = subprocess.Popen(cmd, stdout=streamlit_app_stdout.fileno(), stderr=streamlit_app_stderr.fileno())
    logger.info(f"subprocess start success {streamlit_app_process.pid} uid:{id}")
    await asyncio.sleep(1)
    streamlit_app_stdout.flush()
    streamlit_app_stderr.flush()
    [logger.info(i) for i in streamlit_app_stdout.readlines()]
    [logger.info(i) for i in streamlit_app_stderr.readlines()]


async def close_subprocess() -> None:
    logger.debug("close subprocess")
    try:
        streamlit_app_process.kill()
        streamlit_app_stdout.flush()
        streamlit_app_stderr.flush()
        streamlit_app_stdout.close()
        streamlit_app_stderr.close()
    except Exception as error:
        logger.error(error)


application = FastAPI()
application.add_event_handler("startup", registry_subprocess)
application.add_event_handler("shutdown", close_subprocess)
application.add_middleware(
    CORSMiddleware,
    allow_origins='*',
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
application.mount(f"/{mlflow_app_prefix.strip('/')}", WSGIMiddleware(mlflow_app))

if __name__ == "__main__":
    uvicorn.run(application, host=mlflow_app_host, port=int(mlflow_app_port))


  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 14 '22 at 18:00