Update server.py
Browse files
server.py
CHANGED
|
@@ -8,10 +8,13 @@ all original behaviour unchanged.
|
|
| 8 |
|
| 9 |
Behaviour:
|
| 10 |
- If ZD_HEADLESS is True, zendriver will run headless as before.
|
| 11 |
-
- If ZD_HEADLESS is False and
|
| 12 |
-
start a pyvirtualdisplay.Display (Xvfb)
|
| 13 |
-
browsers. If pyvirtualdisplay is not
|
| 14 |
-
we log a warning and continue.
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
To run on Hugging Face Spaces, add `pyvirtualdisplay` to requirements.txt
|
| 17 |
and ensure `xvfb` is available in the runtime (HF Spaces typically provide it).
|
|
@@ -71,6 +74,13 @@ CLICK_INTERVAL = 0.35
|
|
| 71 |
CLICK_JITTER = 8.0
|
| 72 |
KEY_PREFIX = "userKey"
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
# --- HTTP / generation ---
|
| 75 |
HTTP_TIMEOUT = 30
|
| 76 |
MAX_DOWNLOAD_WAIT = 180
|
|
@@ -157,7 +167,7 @@ def _stamp() -> str:
|
|
| 157 |
def _start_virtual_display_if_needed(headless: bool):
|
| 158 |
"""
|
| 159 |
Start pyvirtualdisplay.Display() if we're running non-headless in an
|
| 160 |
-
environment without DISPLAY.
|
| 161 |
This function is synchronous and safe to be run in a thread executor.
|
| 162 |
"""
|
| 163 |
global VDISPLAY
|
|
@@ -166,6 +176,10 @@ def _start_virtual_display_if_needed(headless: bool):
|
|
| 166 |
log.info("ZD_HEADLESS=True → not starting virtual display")
|
| 167 |
return
|
| 168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
if os.environ.get("DISPLAY"):
|
| 170 |
log.info("DISPLAY already set: %s", os.environ.get("DISPLAY"))
|
| 171 |
return
|
|
@@ -1034,9 +1048,7 @@ async def lifespan(app: FastAPI):
|
|
| 1034 |
_key_refresh_lock = asyncio.Lock()
|
| 1035 |
JOB_QUEUE = asyncio.Queue(maxsize=MAX_QUEUE_SIZE)
|
| 1036 |
|
| 1037 |
-
# If
|
| 1038 |
-
# a virtual display (pyvirtualdisplay/Xvfb). This runs in a thread
|
| 1039 |
-
# executor because pyvirtualdisplay is synchronous.
|
| 1040 |
loop = asyncio.get_running_loop()
|
| 1041 |
try:
|
| 1042 |
await loop.run_in_executor(None, partial(_start_virtual_display_if_needed, ZD_HEADLESS))
|
|
@@ -1325,6 +1337,7 @@ if __name__ == "__main__":
|
|
| 1325 |
|
| 1326 |
# Allow overriding via environment variables
|
| 1327 |
ZD_HEADLESS = os.environ.get("ZD_HEADLESS", str(ZD_HEADLESS)) in ("1", "true", "True")
|
|
|
|
| 1328 |
|
| 1329 |
# If running locally and not headless, start virtual display if needed
|
| 1330 |
try:
|
|
|
|
| 8 |
|
| 9 |
Behaviour:
|
| 10 |
- If ZD_HEADLESS is True, zendriver will run headless as before.
|
| 11 |
+
- If ZD_HEADLESS is False and USE_VIRTUAL_DISPLAY is True and a DISPLAY
|
| 12 |
+
is not present, we attempt to start a pyvirtualdisplay.Display (Xvfb)
|
| 13 |
+
automatically before launching browsers. If pyvirtualdisplay is not
|
| 14 |
+
installed or starting Xvfb fails, we log a warning and continue.
|
| 15 |
+
- If USE_VIRTUAL_DISPLAY is False we will NOT attempt to start a virtual
|
| 16 |
+
display — you must provide a DISPLAY yourself (or set ZD_HEADLESS=True)
|
| 17 |
+
if running on a headless host.
|
| 18 |
|
| 19 |
To run on Hugging Face Spaces, add `pyvirtualdisplay` to requirements.txt
|
| 20 |
and ensure `xvfb` is available in the runtime (HF Spaces typically provide it).
|
|
|
|
| 74 |
CLICK_JITTER = 8.0
|
| 75 |
KEY_PREFIX = "userKey"
|
| 76 |
|
| 77 |
+
# --- Virtual display toggle (new) ---
|
| 78 |
+
# If True the server will attempt to auto-start a pyvirtualdisplay (Xvfb)
|
| 79 |
+
# when no DISPLAY is present and ZD_HEADLESS is False. If False the server
|
| 80 |
+
# will not try to start a virtual display and you must provide a DISPLAY
|
| 81 |
+
# or set ZD_HEADLESS=True.
|
| 82 |
+
USE_VIRTUAL_DISPLAY = True
|
| 83 |
+
|
| 84 |
# --- HTTP / generation ---
|
| 85 |
HTTP_TIMEOUT = 30
|
| 86 |
MAX_DOWNLOAD_WAIT = 180
|
|
|
|
| 167 |
def _start_virtual_display_if_needed(headless: bool):
|
| 168 |
"""
|
| 169 |
Start pyvirtualdisplay.Display() if we're running non-headless in an
|
| 170 |
+
environment without DISPLAY and USE_VIRTUAL_DISPLAY is True.
|
| 171 |
This function is synchronous and safe to be run in a thread executor.
|
| 172 |
"""
|
| 173 |
global VDISPLAY
|
|
|
|
| 176 |
log.info("ZD_HEADLESS=True → not starting virtual display")
|
| 177 |
return
|
| 178 |
|
| 179 |
+
if not USE_VIRTUAL_DISPLAY:
|
| 180 |
+
log.info("USE_VIRTUAL_DISPLAY=False → not starting virtual display; expecting manual DISPLAY or headless mode.")
|
| 181 |
+
return
|
| 182 |
+
|
| 183 |
if os.environ.get("DISPLAY"):
|
| 184 |
log.info("DISPLAY already set: %s", os.environ.get("DISPLAY"))
|
| 185 |
return
|
|
|
|
| 1048 |
_key_refresh_lock = asyncio.Lock()
|
| 1049 |
JOB_QUEUE = asyncio.Queue(maxsize=MAX_QUEUE_SIZE)
|
| 1050 |
|
| 1051 |
+
# If configured to start virtual display, attempt to do so when needed.
|
|
|
|
|
|
|
| 1052 |
loop = asyncio.get_running_loop()
|
| 1053 |
try:
|
| 1054 |
await loop.run_in_executor(None, partial(_start_virtual_display_if_needed, ZD_HEADLESS))
|
|
|
|
| 1337 |
|
| 1338 |
# Allow overriding via environment variables
|
| 1339 |
ZD_HEADLESS = os.environ.get("ZD_HEADLESS", str(ZD_HEADLESS)) in ("1", "true", "True")
|
| 1340 |
+
USE_VIRTUAL_DISPLAY = os.environ.get("USE_VIRTUAL_DISPLAY", str(USE_VIRTUAL_DISPLAY)) in ("1", "true", "True")
|
| 1341 |
|
| 1342 |
# If running locally and not headless, start virtual display if needed
|
| 1343 |
try:
|