Fix Space RUNTIME_ERROR: publish demo=app.blocks for SpacesReloader, block_thread to stay alive
Browse files
server.py
CHANGED
|
@@ -326,25 +326,35 @@ async def index():
|
|
| 326 |
return FileResponse(FRONTEND / "index.html")
|
| 327 |
|
| 328 |
|
| 329 |
-
# HF runs `python server.py` (README app_file) and proxies port 7860.
|
| 330 |
-
#
|
| 331 |
-
#
|
| 332 |
-
#
|
|
|
|
|
|
|
|
|
|
| 333 |
# * ssr_mode=False — gradio 6 defaults to SSR, which needs a Node front-proxy on
|
| 334 |
-
# 7860 and pushes
|
| 335 |
-
#
|
| 336 |
-
# *
|
| 337 |
-
#
|
| 338 |
-
#
|
| 339 |
-
#
|
| 340 |
-
#
|
| 341 |
-
#
|
| 342 |
-
#
|
| 343 |
-
# the
|
| 344 |
-
# HF sets the env in the parent before this module is imported.)
|
| 345 |
app.launch(
|
| 346 |
server_name="0.0.0.0",
|
| 347 |
server_port=int(os.getenv("PORT", "7860")),
|
| 348 |
ssr_mode=False,
|
|
|
|
| 349 |
show_error=True,
|
| 350 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
return FileResponse(FRONTEND / "index.html")
|
| 327 |
|
| 328 |
|
| 329 |
+
# HF runs `python server.py` (README app_file) and proxies port 7860. Launch
|
| 330 |
+
# happens at MODULE TOP LEVEL (gradio.Server, like gradio's reference example).
|
| 331 |
+
#
|
| 332 |
+
# Running on a Space is fiddly because gradio *always* routes through its
|
| 333 |
+
# SpacesReloader there (regardless of GRADIO_HOT_RELOAD). `launch()` starts the
|
| 334 |
+
# uvicorn server AND a daemon "watch" thread (spaces.reloading) whose `postrun`
|
| 335 |
+
# does `getattr(__main__, "demo")` and compares it to the live Blocks. So:
|
| 336 |
# * ssr_mode=False — gradio 6 defaults to SSR, which needs a Node front-proxy on
|
| 337 |
+
# 7860 and pushes Python to 7861; on a Space (no Node) that fails the 7860
|
| 338 |
+
# health check. Disabling SSR binds the Python server directly on 7860.
|
| 339 |
+
# * prevent_thread_lock=True — return from launch() so we can publish `demo`
|
| 340 |
+
# before holding the thread ourselves.
|
| 341 |
+
# * `demo = app.blocks` — the watcher requires a module global named `demo` that
|
| 342 |
+
# *is* the running Blocks. gradio.Server only populates `.blocks` during
|
| 343 |
+
# launch, so we must assign it AFTER. If it's missing (or isn't the live
|
| 344 |
+
# Blocks), postrun raises / tries to swap a non-Blocks and the Space dies with
|
| 345 |
+
# RUNTIME_ERROR. We do NOT mount the legacy app.py Blocks (a second `demo`
|
| 346 |
+
# would collide); the standalone Gradio UI is still available via `python app.py`.
|
|
|
|
| 347 |
app.launch(
|
| 348 |
server_name="0.0.0.0",
|
| 349 |
server_port=int(os.getenv("PORT", "7860")),
|
| 350 |
ssr_mode=False,
|
| 351 |
+
prevent_thread_lock=True,
|
| 352 |
show_error=True,
|
| 353 |
)
|
| 354 |
+
|
| 355 |
+
# Expose the live Blocks as the module global the SpacesReloader's postrun expects.
|
| 356 |
+
demo = app.blocks
|
| 357 |
+
|
| 358 |
+
# launch() returned (prevent_thread_lock); the server + watch threads are daemons,
|
| 359 |
+
# so hold the main thread open to keep them — and the Space — alive.
|
| 360 |
+
app.blocks.block_thread()
|