""" launch.py Launcher script to run both FastAPI backend and Streamlit frontend. - For local development: Starts both services on different ports - For Hugging Face Spaces: Configured to work with the Spaces proxy """ import os import subprocess import threading import time import signal import sys # Configuration FASTAPI_PORT = 7860 STREAMLIT_PORT = 8501 IS_SPACE = "SPACE_ID" in os.environ # Check if running on Hugging Face Spaces # Define commands to run services if IS_SPACE: # On Hugging Face Spaces, we need to bind to 0.0.0.0 to allow external access fastapi_cmd = ["python", "-m", "uvicorn", "api_backend:app", "--host", "0.0.0.0", "--port", str(FASTAPI_PORT)] streamlit_cmd = ["streamlit", "run", "app.py", "--server.address", "0.0.0.0", "--server.port", str(STREAMLIT_PORT)] else: # For local development fastapi_cmd = ["python", "-m", "uvicorn", "api_backend:app", "--port", str(FASTAPI_PORT)] streamlit_cmd = ["streamlit", "run", "app.py", "--server.port", str(STREAMLIT_PORT)] # Processes to track for cleanup processes = [] # Signal handler for graceful shutdown def handle_shutdown(signum, frame): print("\nShutting down all services...") for process in processes: if process.poll() is None: # Check if process is still running process.terminate() sys.exit(0) # Register signal handlers for graceful shutdown signal.signal(signal.SIGINT, handle_shutdown) signal.signal(signal.SIGTERM, handle_shutdown) def run_service(cmd, service_name): """Run a service process and capture its output.""" print(f"Starting {service_name}...") process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, bufsize=1 ) processes.append(process) # Print process output with service identifier for line in process.stdout: print(f"[{service_name}] {line}", end="") # If we get here, the process has ended print(f"{service_name} has stopped.") # Main execution if __name__ == "__main__": print("🚀 Starting Flowchart-to-English services") # Start FastAPI in a separate thread fastapi_thread = threading.Thread( target=run_service, args=(fastapi_cmd, "FastAPI"), daemon=True ) fastapi_thread.start() # Give FastAPI a moment to start up time.sleep(2) # Start Streamlit (in the main thread) run_service(streamlit_cmd, "Streamlit")