Files
pyisolate/README_COMFYUI.md
zeekay 579df57d8e fix: correct repo owner (hanzoai/studio) and restore third-party URLs
- hanzoui/studio → hanzoai/studio (main repo is under hanzoai org)
- hanzoui/studio-Manager → hanzoui/manager (correct repo name)
- Restore ltdrdata/ComfyUI-Manager (third-party, not ours)
- Fix filesystem paths with spaces (Hanzo Studio → HanzoStudio)
- Fix GitHub API repo slugs ("Hanzo Studio" → "studio")
2026-02-23 15:27:37 -08:00

11 KiB

PyIsolate for Hanzo Studio Custom Nodes

Process isolation for Hanzo Studio custom nodes - solve dependency conflicts without breaking your workflow.

🎯 Quick Start: Get your custom node isolated in under 5 minutes. See Installation and Converting Your Node.

What Problem Does This Solve?

Hanzo Studio custom nodes often require conflicting dependencies:

  • Node A needs numpy==1.24.0
  • Node B needs numpy==2.0.0
  • Both can't coexist in the same environment

PyIsolate solution: Each custom node runs in its own isolated process with its own dependencies, while sharing PyTorch tensors with zero-copy performance.

Installation

Prerequisites

  • Python 3.9+
  • Hanzo Studio installed
  • The uv package manager

Install uv (if not already installed)

# Linux/macOS
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

Install PyIsolate in Hanzo Studio

cd Hanzo Studio
source .venv/bin/activate  # Windows: .venv\Scripts\activate

Clone from pollockjj's repo:
git clone https://github.com/pollockjj/pyisolate
cd pyisolate
git install .

Enable Isolation in Hanzo Studio

Add the --use-process-isolation flag when launching Hanzo Studio:

python main.py --use-process-isolation

That's it. Hanzo Studio will now automatically detect and isolate any custom nodes with a pyisolate.yaml manifest.


Converting a Custom Node

Step 1: Create pyisolate.yaml

In the custom node directory, create a pyisolate.yaml file:

# custom_nodes/MyAwesomeNode/pyisolate.yaml
isolated: true
share_torch: true  # Enable `zero-copy` PyTorch tensor sharing - Allows fast copy of tensors, but at a higher memory and filespace footprint

dependencies:
  - numpy==2.0.0        # Node specific numpy version
  - pillow==10.0.0      # Node specific dependencies
  - my-special-lib>=1.5

Step 2: Test It

cd Hanzo Studio
python main.py --use-process-isolation

Expected logs - Loading: PyIsolate and internal functions that use it use a "][" as log prefix.

][ HanzoStudio-IsolationTest cache miss, spawning process for metadata  # First run or cache invalidation
][ HanzoStudio-PyIsolatedV3 loaded from cache                           # Subsequent runs where nodes and environment is unchanged so cache is reused
][ HanzoStudio-APIsolated loaded from cache
][ HanzoStudio-DepthAnythingV2 loaded from cache

][ HanzoStudio-IsolationTest metadata cached
][ HanzoStudio-IsolationTest ejecting after metadata extraction

Expected logs - Reporting:

Import times for custom nodes:
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/websocket_image_save.py
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/hanzo-studio-florence2
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/hanzo-studio-videohelpersuite
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-GGUF
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/hanzo-studio-kjnodes
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/ComfyUI-Manager
   0.1 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-Crystools
   0.3 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-WanVideoWrapper
   0.4 seconds: /path/to/HanzoStudio/custom_nodes/RES4LYF


Import times for isolated custom nodes:
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-DepthAnythingV2
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-PyIsolatedV3
   0.0 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-APIsolated
   3.2 seconds: /path/to/HanzoStudio/custom_nodes/HanzoStudio-IsolationTest     #First-time cost

Expected logs - during workflow usage:

got prompt  # A new workflow where isolated nodes are used
][ HanzoStudio-PyIsolatedV3 - just-in-time spawning of isolated custom_node
][ HanzoStudio-APIsolated - just-in-time spawning of isolated custom_node
Prompt executed in 68.34 seconds

got prompt  # same workflow
Prompt executed in 61.68 seconds

got prompt  # different workflow, same two custom_nodes used
Prompt executed in 72.29 seconds

got prompt  # same 2nd workflow as above
Prompt executed in 66.17 seconds

got prompt   # new workflow, no isolated nodes used
][ HanzoStudio-APIsolated isolated custom_node not in execution graph, evicting
][ HanzoStudio-PyIsolatedV3 isolated custom_node not in execution graph, evicting
Prompt executed in 8.49 seconds

What Works

✅ Standard Python code execution:

  • Any standard Python code inside node functions using Comfy standard imports and each custom_node's pysiolate.yaml's dependencies
  • Custom dependencies and conflicting library versions in isolated custom_nodes

✅ Zero-copy tensor sharing (linux only):

  • PyTorch tensors pass between processes without serialization
  • ~1ms overhead per RPC call
  • No memory duplication

✅ Hanzo Studio V3 API support - at least one node tested with (comfy_api.latest):

Core

  • io.ComfyNode
  • io.NodeOutput
  • io.Schema

Numeric & Combo

  • io.Int, io.Int.Input
  • io.Float, io.Float.Input, io.Float.Output
  • io.Combo, io.Combo.Input

Text & Flags

  • io.String, io.String.Input
  • io.Boolean, io.Boolean.Input

Images, Latents, Conditioning

  • io.Image, io.Image.Input, io.Image.Type
  • io.Latent, io.Latent.Input, io.Latent.Output
  • io.Conditioning, io.Conditioning.Input, io.Conditioning.Output
  • io.Sigmas, io.Sigmas.Input

Models & Samplers

  • io.Model, io.Model.Input, io.Model.Output
  • io.Vae, io.Vae.Input
  • io.Sampler.Input
  • io.UpscaleModel, io.UpscaleModel.Input, io.UpscaleModel.Output
  • io.LatentUpscaleModel.Input, io.LatentUpscaleModel.Output
  • io.ControlNet.Output
  • io.Guider.Input
  • io.WanCameraEmbedding, io.WanCameraEmbedding.Input

CLIP / Vision

  • io.ClipVisionOutput, io.ClipVisionOutput.Input

Media

  • io.Video, io.Video.Input, io.Video.Output
  • io.Audio, io.Audio.Output
  • io.AudioEncoder.Input, io.AudioEncoder.Output, io.AudioEncoderOutput.Output

Geometry / Voxel

  • io.Mesh, io.Mesh.Input, io.Mesh.Output
  • io.Voxel, io.Voxel.Input, io.Voxel.Output

Misc

  • io.Hidden, io.Hidden.prompt, io.Hidden.extra_pnginfo
  • io.FolderType, io.FolderType.output
  • io.MatchType, io.MatchType.Input, io.MatchType.Output, io.MatchType.Template
  • io.Photomaker.Input, io.Photomaker.Output
  • io.UploadType, io.UploadType.video
  • io.AnyType, io.AnyType.Output

See Appendix: Supported APIs for complete function lists.

✅ Hanzo Studio core proxies (fully supported):

  • model_management.py - Device management, memory operations, interrupt handling
  • folder_paths.py - Path resolution, model discovery, file operations
  • All functions callable from isolated nodes via transparent RPC

✅ Hanzo Studio standard V1 types that work across isolation:

Input/Output Type Status Notes
IMAGE ✅ Works PyTorch tensor, zero-copy
MASK ✅ Works PyTorch tensor, zero-copy
LATENT ✅ Works Dict with tensor, serializes cleanly
INT ✅ Works Primitive type
FLOAT ✅ Works Primitive type
STRING ✅ Works Primitive type
BOOLEAN ✅ Works Primitive type
CONDITIONING ✅ Works List of tuples with tensors
CONTROL_NET unknown Not tested
MODEL ⚠️ Basic ModelPatcher object, standard inference
CLIP ⚠️ Basic standard CLIP decoding tested isolated
VAE ⚠️ Basic standard VAE decoding tested isolated

Key insight: Any Hanzo Studio type that is fundamentally a tensor, dict, list, or primitive will work. Complex stateful objects like MODEL, CLIP, VAE cannot cross the isolation boundary (yet).

✅ Dependency conflicts of isolated custom_nodes

  • Different numpy versions, diffusers, etc.

What Doesn't Work

❌ PromptServer route decoration:

# This pattern does NOT work
from server import PromptServer
@PromptServer.instance.routes.get("/my_route")
def my_handler(request):
    pass

Why: Route decorators execute at module import time, before isolation is ready.
Workaround: Use route_manifest.json (see Advanced: Web Routes).

❌ Monkey patching Hanzo Studio core:

# This will NEVER work in isolation
import comfy.model_management
comfy.model_management.some_function = my_patched_version

Why: Each isolated process has its own copy of Hanzo Studio code. Patches don't propagate.
Solution: Don't monkey patch. Use proper extension patterns instead.


Live Examples

Three working isolated custom node packs are available for reference:

Node Pack What It Does Isolation Benefit
HanzoStudio-PyIsolatedV3 Demo node using deepdiff Shows basic isolation setup
HanzoStudio-APIsolated API nodes (OpenAI, Gemini, etc.) Isolated API dependencies
HanzoStudio-IsolationTest 70+ Hanzo Studio core nodes Proves isolation doesn't break functionality

Performance Characteristics

Startup Time

Scenario Time Notes
First run (cache miss) speed dependent environment Creates venv, installs deps, caches metadata
Subsequent runs (cache hit) almost instantaneous Loads cached metadata, no spawn
Process spawn on first execution 1-3 seconds (background) Only when node first executes in workflow

Runtime Overhead

Operation Overhead Impact
RPC call (simple data) ~0.3ms Negligible
Tensor passing (share_torch) ~1ms Zero-copy, minimal
Large model loading Same as non-isolated No overhead

Memory Footprint

  • Per isolated node: ~50-300MB
  • Tensors: Shared memory (no duplication)
  • Models: Can be shared via ProxiedSingleton

Bottom line: Isolation adds ~1-2ms per node execution. For typical workflows (seconds per generation), this is <0.1% overhead.


Troubleshooting

"Cache miss, spawning process" on every startup

Cause: Cache invalidated (code changed, manifest changed, or Python version changed). Fix: Normal behavior on first run or after updates. Subsequent runs will be fast.

"Module not found" errors in isolated node

Cause: Dependency not listed in pyisolate.yaml. Fix: Add the missing package to the dependencies list.

Node works non-isolated but fails isolated

Cause: Likely using a pattern that doesn't work with isolation (see What Doesn't Work). Fix: Check logs for specific error, review the node's __init__.py for module-level side effects.

"Torch already imported" warning spam

Cause: Isolated processes reload torch, triggering Hanzo Studio's warning. Fix: Known issue