ibuilder / run_combined.py
Soufianesejjari's picture
Add Docker support, configure environment settings, and enhance API integration
9995fd4
"""
Script to run both the Streamlit app and FastAPI server together.
This is used for deployment in environments like Hugging Face Spaces.
"""
import os
import sys
import subprocess
import time
import signal
import logging
from config import get_settings
settings = get_settings()
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger("run_combined")
def run_streamlit():
"""Run the Streamlit app"""
streamlit_port = os.environ.get("STREAMLIT_SERVER_PORT", "7860")
logger.info(f"Starting Streamlit app on port {streamlit_port}...")
streamlit_process = subprocess.Popen(
[sys.executable, "-m", "streamlit", "run", "app.py",
f"--server.port={streamlit_port}",
"--server.address=0.0.0.0",
"--server.enableCORS=true",
"--server.enableXsrfProtection=false"]
)
return streamlit_process
def run_api():
"""Run the FastAPI server"""
api_port = settings.API_PORT
logger.info(f"Starting FastAPI server on port {api_port}...")
api_process = subprocess.Popen(
[sys.executable, "-m", "uvicorn", "api:app",
"--host", "0.0.0.0",
"--port", str(api_port),
"--log-level", "info"]
)
return api_process
def handle_termination(api_process, streamlit_process):
"""Handle graceful termination"""
def terminate_handler(signum, frame):
logger.info("Received termination signal. Shutting down...")
api_process.terminate()
streamlit_process.terminate()
sys.exit(0)
signal.signal(signal.SIGINT, terminate_handler)
signal.signal(signal.SIGTERM, terminate_handler)
if __name__ == "__main__":
# Start both services
api_process = run_api()
streamlit_process = run_streamlit()
# Set up termination handler
handle_termination(api_process, streamlit_process)
logger.info("Both services started!")
logger.info(f"FastAPI server running on http://localhost:{settings.API_PORT}")
logger.info(f"Streamlit app running on http://localhost:{os.environ.get('STREAMLIT_SERVER_PORT', '7860')}")
try:
# Keep the main process running
while True:
# Check if processes are still running
if api_process.poll() is not None:
logger.error("API server stopped unexpectedly! Restarting...")
api_process = run_api()
if streamlit_process.poll() is not None:
logger.error("Streamlit app stopped unexpectedly! Restarting...")
streamlit_process = run_streamlit()
time.sleep(5)
except KeyboardInterrupt:
logger.info("Stopping services...")
api_process.terminate()
streamlit_process.terminate()
sys.exit(0)