update minio port
This commit is contained in:
180
backend/app/algo_host/subprocess_runner.py
Normal file
180
backend/app/algo_host/subprocess_runner.py
Normal file
@@ -0,0 +1,180 @@
|
||||
"""Spawn reference bundle child processes (main.py, visualize_result_video.py)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from app.algo_host.bundle import load_reference_default_config, resolve_bundle_relative_path
|
||||
from app.algo_host.transcode import VISUALIZATION_MAX_WIDTH
|
||||
|
||||
|
||||
def build_reference_env() -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
env["PYTHONFAULTHANDLER"] = "1"
|
||||
env["PYTHONUNBUFFERED"] = "1"
|
||||
return env
|
||||
|
||||
|
||||
def build_batch_main_command(*, bundle_dir: Path, config_path: Path) -> list[str]:
|
||||
return [
|
||||
"uv",
|
||||
"run",
|
||||
"python",
|
||||
"-X",
|
||||
"faulthandler",
|
||||
str(bundle_dir / "main.py"),
|
||||
"--config",
|
||||
str(config_path),
|
||||
]
|
||||
|
||||
|
||||
def build_visualization_command(
|
||||
*,
|
||||
bundle_dir: Path,
|
||||
video_path: Path,
|
||||
result_path: Path,
|
||||
output_video_path: Path,
|
||||
) -> list[str]:
|
||||
cfg = load_reference_default_config(bundle_dir)
|
||||
weights = cfg.get("weights") if isinstance(cfg.get("weights"), dict) else {}
|
||||
device_cfg = cfg.get("device") if isinstance(cfg.get("device"), dict) else {}
|
||||
hand_raw = str((weights or {}).get("hand") or "weights/hand_detect.pt").strip()
|
||||
hand_model = resolve_bundle_relative_path(bundle_dir, hand_raw)
|
||||
return [
|
||||
sys.executable,
|
||||
"-X",
|
||||
"faulthandler",
|
||||
str((bundle_dir / "visualize_result_video.py").resolve()),
|
||||
"--video",
|
||||
str(video_path.resolve()),
|
||||
"--result-txt",
|
||||
str(result_path.resolve()),
|
||||
"--hand-model",
|
||||
str(hand_model),
|
||||
"--out-video",
|
||||
str(output_video_path.resolve()),
|
||||
"--device",
|
||||
str(device_cfg.get("type") or "cuda"),
|
||||
"--max-width",
|
||||
str(VISUALIZATION_MAX_WIDTH),
|
||||
]
|
||||
|
||||
|
||||
def _signal_name(signum: int) -> str:
|
||||
try:
|
||||
return signal.Signals(signum).name
|
||||
except ValueError:
|
||||
return f"signal {signum}"
|
||||
|
||||
|
||||
def describe_batch_returncode(returncode: int) -> str:
|
||||
if returncode < 0:
|
||||
signum = -returncode
|
||||
return f"terminated by {_signal_name(signum)} ({signum})"
|
||||
if returncode > 128:
|
||||
wrapped = returncode - 256
|
||||
if wrapped < 0:
|
||||
signum = -wrapped
|
||||
return f"exit={returncode} (possibly propagated {wrapped}/{_signal_name(signum)})"
|
||||
return f"exit={returncode}"
|
||||
|
||||
|
||||
def format_batch_failure(
|
||||
returncode: int,
|
||||
*,
|
||||
stdout: str,
|
||||
stderr: str,
|
||||
work_dir: Path,
|
||||
output_path: Path,
|
||||
) -> str:
|
||||
chunks: list[str] = [
|
||||
describe_batch_returncode(returncode),
|
||||
f"work_dir={work_dir}",
|
||||
f"output={output_path}",
|
||||
]
|
||||
stdout = stdout.strip()
|
||||
stderr = stderr.strip()
|
||||
if stdout:
|
||||
chunks.append(f"stdout:\n{stdout[-3000:]}")
|
||||
if stderr:
|
||||
chunks.append(f"stderr:\n{stderr[-3000:]}")
|
||||
return "\n".join(chunks)
|
||||
|
||||
|
||||
def _log_subprocess_output(prefix: str, stdout: str, stderr: str, *, max_lines: int = 40) -> None:
|
||||
for label, text in (("stdout", stdout), ("stderr", stderr)):
|
||||
lines = [ln for ln in (text or "").splitlines() if ln.strip()]
|
||||
if not lines:
|
||||
continue
|
||||
tail = lines[-max_lines:] if len(lines) > max_lines else lines
|
||||
for line in tail:
|
||||
logger.info("{} {}", prefix, line)
|
||||
|
||||
|
||||
def run_subprocess(
|
||||
cmd: list[str],
|
||||
*,
|
||||
cwd: Path,
|
||||
work_dir: Path,
|
||||
output_path: Path,
|
||||
log_label: str,
|
||||
) -> None:
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
cwd=str(cwd),
|
||||
check=False,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
env=build_reference_env(),
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
msg = format_batch_failure(
|
||||
proc.returncode,
|
||||
stdout=proc.stdout or "",
|
||||
stderr=proc.stderr or "",
|
||||
work_dir=work_dir,
|
||||
output_path=output_path,
|
||||
)
|
||||
raise RuntimeError(f"{log_label} failed {msg}")
|
||||
_log_subprocess_output(log_label, proc.stdout or "", proc.stderr or "")
|
||||
|
||||
|
||||
def run_batch_main(*, bundle_dir: Path, config_path: Path, work_dir: Path, output_path: Path) -> None:
|
||||
cmd = build_batch_main_command(bundle_dir=bundle_dir, config_path=config_path)
|
||||
logger.info("reference batch starting: {}", " ".join(cmd))
|
||||
run_subprocess(
|
||||
cmd,
|
||||
cwd=bundle_dir,
|
||||
work_dir=work_dir,
|
||||
output_path=output_path,
|
||||
log_label="reference batch",
|
||||
)
|
||||
|
||||
|
||||
def run_visualization_script(
|
||||
*,
|
||||
bundle_dir: Path,
|
||||
video_path: Path,
|
||||
result_path: Path,
|
||||
raw_output_video_path: Path,
|
||||
) -> None:
|
||||
cmd = build_visualization_command(
|
||||
bundle_dir=bundle_dir,
|
||||
video_path=video_path,
|
||||
result_path=result_path,
|
||||
output_video_path=raw_output_video_path,
|
||||
)
|
||||
logger.info("reference visualization starting: {}", " ".join(cmd))
|
||||
run_subprocess(
|
||||
cmd,
|
||||
cwd=bundle_dir,
|
||||
work_dir=raw_output_video_path.parent,
|
||||
output_path=raw_output_video_path,
|
||||
log_label="visualize",
|
||||
)
|
||||
Reference in New Issue
Block a user