Files
SchwenderOneandClaude Opus 4.8 08b3e49c3d ComfyUI-EnvProbe: report torch/CUDA/Python + dep imports
One diagnostic node (Env Probe, utils/debug) to read a host ComfyUI
runtime without terminal access — used to decide the RunComfy port
strategy for ComfyUI-Human3R.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 00:15:28 +02:00

94 lines
3.2 KiB
Python

"""Env Probe node — reports the host ComfyUI runtime environment.
Single node, no inputs, OUTPUT_NODE so it executes on its own in a one-node
workflow. It prints the report to the server console (visible in RunComfy's log
panel) AND returns it as a STRING you can wire into a Show/Preview Text node, AND
surfaces it in the node's own UI via the {"ui": {"text": ...}} channel.
"""
import sys
import platform
import importlib
def _torch_block():
lines = []
try:
import torch
lines.append(f"torch.__version__ = {torch.__version__}")
lines.append(f"torch.version.cuda = {torch.version.cuda}")
try:
lines.append(f"torch.backends.cudnn = {torch.backends.cudnn.version()}")
except Exception as e:
lines.append(f"torch.backends.cudnn = <error: {e}>")
avail = torch.cuda.is_available()
lines.append(f"torch.cuda.is_available= {avail}")
if avail:
lines.append(f"device_count = {torch.cuda.device_count()}")
for i in range(torch.cuda.device_count()):
name = torch.cuda.get_device_name(i)
cap = torch.cuda.get_device_capability(i)
lines.append(f" cuda:{i} = {name} (sm_{cap[0]}{cap[1]})")
except Exception as e:
lines.append(f"torch import FAILED: {e!r}")
return lines
def _dep_block():
# Deps relevant to the ComfyUI-Human3R port. We only check importability +
# version here; this tells us what RunComfy's Manager already resolves vs.
# what we must ship. 'curope' is the bundled compiled CUDA extension — if it
# is NOT importable, Human3R falls back to a pure-PyTorch RoPE2D.
deps = ["numpy", "smplx", "roma", "trimesh", "gsplat", "einops", "cv2"]
lines = []
for mod in deps:
try:
m = importlib.import_module(mod)
ver = getattr(m, "__version__", "?")
lines.append(f" {mod:<10} OK {ver}")
except Exception as e:
lines.append(f" {mod:<10} MISSING ({type(e).__name__})")
return lines
def build_report():
lines = []
lines.append("=" * 56)
lines.append(" ComfyUI Env Probe")
lines.append("=" * 56)
lines.append(f"sys.version = {sys.version.split(chr(10))[0]}")
lines.append(f"platform = {platform.platform()}")
lines.append("-" * 56)
lines.extend(_torch_block())
lines.append("-" * 56)
lines.append("dependency import check (for Human3R port):")
lines.extend(_dep_block())
lines.append("=" * 56)
return "\n".join(lines)
class EnvProbe:
@classmethod
def INPUT_TYPES(cls):
return {"required": {}}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("report",)
FUNCTION = "run"
CATEGORY = "utils/debug"
OUTPUT_NODE = True
@classmethod
def IS_CHANGED(cls, **kwargs):
# Always re-run so the probe is never skipped by ComfyUI's result cache.
return float("nan")
def run(self):
report = build_report()
print("\n" + report + "\n", flush=True)
return {"ui": {"text": [report]}, "result": (report,)}
NODE_CLASS_MAPPINGS = {"EnvProbe": EnvProbe}
NODE_DISPLAY_NAME_MAPPINGS = {"EnvProbe": "Env Probe"}