- 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")
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
uvpackage 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 handlingfolder_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