97 lines
3.3 KiB
Python
97 lines
3.3 KiB
Python
"""Einstiegspunkt für die gebundelte Tätigkeitsnachweis-Generator .exe.
|
|
|
|
Wird von PyInstaller als Entry-Point verwendet. Im gebundelten Modus
|
|
(sys.frozen = True) liegen die Python-Dateien (app.py, src/) in sys._MEIPASS,
|
|
während die Daten-Ordner (config/, input/, template/, output/) neben der .exe
|
|
erwartet werden.
|
|
|
|
Dieses Skript:
|
|
1. Setzt APP_BASE_DIR auf das Verzeichnis der .exe
|
|
2. Fügt sys._MEIPASS zum Python-Pfad hinzu (für src/-Imports)
|
|
3. Startet den Streamlit-Server und öffnet den Browser
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import threading
|
|
import time
|
|
import webbrowser
|
|
from pathlib import Path
|
|
|
|
|
|
def _get_base_dir() -> Path:
|
|
"""Verzeichnis der .exe (bzw. des Skripts im Entwicklungsmodus)."""
|
|
if getattr(sys, 'frozen', False):
|
|
return Path(sys.executable).resolve().parent
|
|
else:
|
|
# Entwicklungsmodus: run.py liegt in 1_build-pipeline/,
|
|
# die App in 0_application/
|
|
return Path(__file__).resolve().parent.parent / "0_application"
|
|
|
|
|
|
def _get_app_path() -> str:
|
|
"""Pfad zur app.py (gebundelt oder im Entwicklungsmodus)."""
|
|
if getattr(sys, 'frozen', False):
|
|
return os.path.join(sys._MEIPASS, "app.py")
|
|
else:
|
|
return str(Path(__file__).resolve().parent.parent / "0_application" / "app.py")
|
|
|
|
|
|
def _ensure_dirs(base_dir: Path) -> None:
|
|
"""Stellt sicher, dass input/, output/, template/, config/ existieren."""
|
|
for folder in ["input", "output", "template", "config"]:
|
|
(base_dir / folder).mkdir(exist_ok=True)
|
|
|
|
|
|
def main() -> None:
|
|
base_dir = _get_base_dir()
|
|
|
|
# Im gebundelten Modus: sys._MEIPASS enthält src/ und app.py
|
|
if getattr(sys, 'frozen', False):
|
|
if sys._MEIPASS not in sys.path:
|
|
sys.path.insert(0, sys._MEIPASS)
|
|
|
|
# APP_BASE_DIR teilt app.py mit, wo die Daten-Ordner liegen
|
|
os.environ["APP_BASE_DIR"] = str(base_dir)
|
|
|
|
_ensure_dirs(base_dir)
|
|
|
|
# ── Streamlit-Konfiguration ──────────────────────────
|
|
os.environ["STREAMLIT_SERVER_ADDRESS"] = "localhost"
|
|
os.environ["STREAMLIT_SERVER_PORT"] = "8501"
|
|
os.environ["STREAMLIT_SERVER_HEADLESS"] = "true"
|
|
os.environ["STREAMLIT_BROWSER_GATHER_USAGE_STATS"] = "false"
|
|
os.environ["STREAMLIT_SERVER_ENABLE_CORS"] = "false"
|
|
os.environ["STREAMLIT_SERVER_ENABLE_XSRF_PROTECTION"] = "false"
|
|
|
|
# Browser manuell öffnen
|
|
def _open_browser() -> None:
|
|
time.sleep(2)
|
|
webbrowser.open("http://localhost:8501")
|
|
|
|
threading.Thread(target=_open_browser, daemon=True).start()
|
|
|
|
# ── Streamlit via CLI-Codepfad starten ───────────────
|
|
# Dieser Weg ist identisch zu 'streamlit run app.py' und
|
|
# funktioniert im PyInstaller-Bundle zuverlässiger als
|
|
# bootstrap.run() mit Streamlit >= 1.58.
|
|
sys.argv = [
|
|
"streamlit", "run", _get_app_path(),
|
|
"--server.port=8501",
|
|
"--server.address=localhost",
|
|
"--server.headless=true",
|
|
"--browser.gatherUsageStats=false",
|
|
"--server.enableCORS=false",
|
|
"--server.enableXsrfProtection=false",
|
|
"--global.developmentMode=false",
|
|
]
|
|
try:
|
|
from streamlit.cli import main as cli_main
|
|
except ImportError:
|
|
from streamlit.web.cli import main as cli_main
|
|
cli_main()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|