from __future__ import annotations import os import socket import sys import threading import time import webbrowser from pathlib import Path from streamlit.web import bootstrap def _resource_root() -> Path: if hasattr(sys, "_MEIPASS"): return Path(getattr(sys, "_MEIPASS")) return Path(__file__).resolve().parent def _find_open_port(host: str = "127.0.0.1") -> int: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, 0)) return int(s.getsockname()[1]) def _open_browser_when_ready(url: str, delay_seconds: float = 1.4) -> None: def _open() -> None: time.sleep(delay_seconds) webbrowser.open(url) threading.Thread(target=_open, daemon=True).start() def main() -> None: root = _resource_root() app_script = root / "app.py" if not app_script.exists(): raise FileNotFoundError(f"Bundled app script not found: {app_script}") os.chdir(root) os.environ.setdefault("STREAMLIT_BROWSER_GATHER_USAGE_STATS", "false") port = _find_open_port() url = f"http://127.0.0.1:{port}" _open_browser_when_ready(url) flags = { "server.headless": True, "server.port": port, "server.address": "127.0.0.1", "browser.serverAddress": "127.0.0.1", "browser.serverPort": port, } bootstrap.run(str(app_script), False, [], flags) if __name__ == "__main__": main()