{"id":47061071,"url":"https://github.com/comfy-org/pyisolate","last_synced_at":"2026-04-12T19:01:23.741Z","repository":{"id":333416524,"uuid":"1008787803","full_name":"Comfy-Org/pyisolate","owner":"Comfy-Org","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-25T11:42:04.000Z","size":3256,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-25T14:59:40.520Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Comfy-Org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-26T05:15:54.000Z","updated_at":"2026-02-25T11:42:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Comfy-Org/pyisolate","commit_stats":null,"previous_names":["comfy-org/pyisolate"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Comfy-Org/pyisolate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comfy-Org%2Fpyisolate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comfy-Org%2Fpyisolate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comfy-Org%2Fpyisolate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comfy-Org%2Fpyisolate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Comfy-Org","download_url":"https://codeload.github.com/Comfy-Org/pyisolate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comfy-Org%2Fpyisolate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30415042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T00:40:14.898Z","status":"online","status_checked_at":"2026-03-12T02:00:07.260Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-12T04:03:19.931Z","updated_at":"2026-04-12T19:01:23.585Z","avatar_url":"https://github.com/Comfy-Org.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyisolate\n\n**Run Python extensions in isolated virtual environments with seamless inter-process communication.**\n\npyisolate enables you to run Python extensions with conflicting dependencies in the same application by automatically creating isolated environments for each extension. Extensions communicate with the host process through a transparent JSON-RPC system, making the isolation invisible to your code while keeping the host environment dependency-free.\n\n## Requirements\n\n- Python 3.10+\n- The [`uv`](https://github.com/astral-sh/uv) CLI available on your `PATH`\n- PyTorch is optional and only required for tensor-sharing features (`share_torch=True`)\n\n## Key Benefits\n\n- **Dependency Isolation**: Run extensions with incompatible dependencies (e.g., numpy 1.x and 2.x) in the same application\n- **Zero-Copy PyTorch Tensor Sharing**: Share PyTorch tensors between processes without serialization overhead\n- **Multiple Environment Backends**: Use `uv` by default or a conda/pixi environment for conda-native dependencies\n- **Bubblewrap Sandboxing**: Deny-by-default filesystem isolation on Linux with GPU passthrough\n- **Transparent Communication**: Call async methods across process boundaries as if they were local\n- **Fast**: Uses `uv` for blazing-fast virtual environment creation\n\n## Installation\n\n```bash\npip install pyisolate\n```\n\nFor development:\n```bash\npip install pyisolate[dev]\n```\n\n## Quick Start\n\n### Basic Usage\n\nCreate an extension that runs in an isolated environment:\n\n```python\n# extensions/my_extension/__init__.py\nfrom pyisolate import ExtensionBase\n\nclass MyExtension(ExtensionBase):\n    def on_module_loaded(self, module):\n        self.module = module\n\n    async def process_data(self, data):\n        # This runs in an isolated process with its own dependencies\n        import numpy as np  # This could be numpy 2.x\n        return np.array(data).mean()\n```\n\nLoad and use the extension from your main application:\n\n```python\n# main.py\nimport pyisolate\nimport asyncio\n\nasync def main():\n    config = pyisolate.ExtensionManagerConfig(\n        venv_root_path=\"./venvs\"\n    )\n    manager = pyisolate.ExtensionManager(pyisolate.ExtensionBase, config)\n\n    extension = manager.load_extension(\n        pyisolate.ExtensionConfig(\n            name=\"data_processor\",\n            module_path=\"./extensions/my_extension\",\n            isolated=True,\n            dependencies=[\"numpy\u003e=2.0.0\"]\n        )\n    )\n\n    result = await extension.process_data([1, 2, 3, 4, 5])\n    print(f\"Mean: {result}\")  # Mean: 3.0\n\n    await extension.stop()\n\nasyncio.run(main())\n```\n\n### PyTorch Tensor Sharing\n\nShare PyTorch tensors between processes without serialization:\n\n```python\nextension = manager.load_extension(\n    pyisolate.ExtensionConfig(\n        name=\"ml_processor\",\n        module_path=\"./extensions/ml_extension\",\n        share_torch=True,          # Enable zero-copy tensor sharing\n        share_cuda_ipc=True,       # CUDA IPC for GPU tensors (Linux)\n    )\n)\n\n# Large tensor is shared via /dev/shm, not serialized\nlarge_tensor = torch.randn(1000, 1000)\nmean = await extension.process_tensor(large_tensor)\n```\n\n### Shared State with Singletons\n\nShare state across all extensions using ProxiedSingleton:\n\n```python\nfrom pyisolate import ProxiedSingleton\n\nclass DatabaseAPI(ProxiedSingleton):\n    def __init__(self):\n        self.data = {}\n\n    def get(self, key):\n        return self.data.get(key)\n\n    def set(self, key, value):\n        self.data[key] = value\n```\n\n```python\n# In any extension — returns proxy to host's real instance\ndb = DatabaseAPI()\nawait db.set(\"result\", result)\n```\n\n### Execution Models\n\npyisolate provides two execution models:\n\n- **`host-coupled`** (default): Child process shares the host's torch runtime and can use zero-copy tensor transfer via `/dev/shm` and CUDA IPC.\n- **`sealed_worker`**: Fully isolated child with its own interpreter. No host `sys.path` reconstruction, JSON-RPC tensor transport only.\n\nAnd two environment backends:\n\n- **`uv`** (default): Fast pip-compatible virtual environments.\n- **`conda`**: pixi-backed conda environments for packages that need conda-forge.\n\n```python\n# Sealed worker with conda environment\nconfig = pyisolate.ExtensionConfig(\n    name=\"weather_processor\",\n    module_path=\"./extensions/weather\",\n    isolated=True,\n    execution_model=\"sealed_worker\",\n    package_manager=\"conda\",\n    share_torch=False,\n    conda_channels=[\"conda-forge\"],\n    conda_dependencies=[\"eccodes\", \"cfgrib\"],\n    dependencies=[\"xarray\", \"cfgrib\"],\n)\n```\n\n### Implementing an Adapter\n\nApplications integrate via the `IsolationAdapter` protocol:\n\n```python\nfrom pyisolate.interfaces import IsolationAdapter\n\nclass MyAppAdapter(IsolationAdapter):\n    @property\n    def identifier(self) -\u003e str:\n        return \"myapp\"\n\n    def get_path_config(self, module_path: str) -\u003e dict:\n        return {\n            \"preferred_root\": \"/path/to/myapp\",\n            \"additional_paths\": [\"/path/to/myapp/extensions\"],\n        }\n\n    def register_serializers(self, registry) -\u003e None:\n        registry.register(\n            \"MyCustomType\",\n            serializer=lambda obj: {\"data\": obj.data},\n            deserializer=lambda d: MyCustomType(d[\"data\"]),\n        )\n\n    def provide_rpc_services(self) -\u003e list:\n        return [MyRegistry, MyProgressReporter]\n```\n\n## Architecture\n\n```\n┌─────────────────────┐     RPC      ┌─────────────┐\n│    Host Process     │◄────────────►│ Extension A │\n│                     │              │  (venv A)   │\n│  ┌──────────────┐   │              └─────────────┘\n│  │   Shared     │   │     RPC      ┌─────────────┐\n│  │ Singletons   │   │◄────────────►│ Extension B │\n│  └──────────────┘   │              │  (venv B)   │\n└─────────────────────┘              └─────────────┘\n```\n\n## Features\n\n### Core\n- Automatic virtual environment management\n- Bidirectional JSON-RPC over Unix Domain Sockets (no pickle)\n- Full async/await support\n- Lifecycle hooks: `before_module_loaded()`, `on_module_loaded()`, `stop()`\n- Error propagation across process boundaries\n\n### Advanced\n- Bubblewrap sandbox with deny-by-default filesystem (Linux)\n- CUDA wheel resolution for custom GPU package builds\n- Zero-copy tensor transfer via CUDA IPC and `/dev/shm`\n- Performance tracing (`PYISOLATE_TRACE_FILE`)\n- Multi-distro sandbox detection (RHEL, Ubuntu, Arch, SELinux)\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `PYISOLATE_CHILD` | Set to `\"1\"` in isolated child processes |\n| `PYISOLATE_DEBUG_RPC` | `\"1\"` for verbose RPC message logging |\n| `PYISOLATE_TRACE_FILE` | Path for structured performance trace output |\n| `PYISOLATE_ENABLE_CUDA_IPC` | `\"1\"` to enable CUDA IPC tensor transport |\n| `PYISOLATE_PATH_DEBUG` | `\"1\"` for detailed sys.path logging during child init |\n\n## Development\n\n```bash\n# Setup development environment\nuv venv \u0026\u0026 source .venv/bin/activate\nuv pip install -e \".[dev,test]\"\npre-commit install\n\n# Run tests\npytest\n\n# Run linting\nruff check pyisolate tests\n\n# Run benchmarks\npython benchmarks/simple_benchmark.py\n```\n\n## Use Cases\n\npyisolate is designed for:\n\n- **Plugin Systems**: When plugins may require conflicting dependencies\n- **ML Pipelines**: Different models requiring different library versions\n- **Microservices in a Box**: Multiple services with different dependencies in one app\n- **Legacy Code Integration**: Wrapping legacy code with specific dependency requirements\n\n## License\n\npyisolate is licensed under the MIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomfy-org%2Fpyisolate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomfy-org%2Fpyisolate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomfy-org%2Fpyisolate/lists"}