Skip to main content

A Python library for dividing execution across multiple virtual environments

Project description

pyisolate

Run Python extensions in isolated virtual environments with seamless inter-process communication.

pyisolate 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.

Requirements

  • Python 3.10+
  • The uv CLI available on your PATH
  • PyTorch is optional and only required for tensor-sharing features (share_torch=True)

Key Benefits

  • Dependency Isolation: Run extensions with incompatible dependencies (e.g., numpy 1.x and 2.x) in the same application
  • Zero-Copy PyTorch Tensor Sharing: Share PyTorch tensors between processes without serialization overhead
  • Multiple Environment Backends: Use uv by default or a conda/pixi environment for conda-native dependencies
  • Bubblewrap Sandboxing: Deny-by-default filesystem isolation on Linux with GPU passthrough
  • Transparent Communication: Call async methods across process boundaries as if they were local
  • Fast: Uses uv for blazing-fast virtual environment creation

Installation

pip install pyisolate

For development:

pip install pyisolate[dev]

Quick Start

Basic Usage

Create an extension that runs in an isolated environment:

# extensions/my_extension/__init__.py
from pyisolate import ExtensionBase

class MyExtension(ExtensionBase):
    def on_module_loaded(self, module):
        self.module = module

    async def process_data(self, data):
        # This runs in an isolated process with its own dependencies
        import numpy as np  # This could be numpy 2.x
        return np.array(data).mean()

Load and use the extension from your main application:

# main.py
import pyisolate
import asyncio

async def main():
    config = pyisolate.ExtensionManagerConfig(
        venv_root_path="./venvs"
    )
    manager = pyisolate.ExtensionManager(pyisolate.ExtensionBase, config)

    extension = manager.load_extension(
        pyisolate.ExtensionConfig(
            name="data_processor",
            module_path="./extensions/my_extension",
            isolated=True,
            dependencies=["numpy>=2.0.0"]
        )
    )

    result = await extension.process_data([1, 2, 3, 4, 5])
    print(f"Mean: {result}")  # Mean: 3.0

    await extension.stop()

asyncio.run(main())

PyTorch Tensor Sharing

Share PyTorch tensors between processes without serialization:

extension = manager.load_extension(
    pyisolate.ExtensionConfig(
        name="ml_processor",
        module_path="./extensions/ml_extension",
        share_torch=True,          # Enable zero-copy tensor sharing
        share_cuda_ipc=True,       # CUDA IPC for GPU tensors (Linux)
    )
)

# Large tensor is shared via /dev/shm, not serialized
large_tensor = torch.randn(1000, 1000)
mean = await extension.process_tensor(large_tensor)

Shared State with Singletons

Share state across all extensions using ProxiedSingleton:

from pyisolate import ProxiedSingleton

class DatabaseAPI(ProxiedSingleton):
    def __init__(self):
        self.data = {}

    def get(self, key):
        return self.data.get(key)

    def set(self, key, value):
        self.data[key] = value
# In any extension — returns proxy to host's real instance
db = DatabaseAPI()
await db.set("result", result)

Execution Models

pyisolate provides two execution models:

  • host-coupled (default): Child process shares the host's torch runtime and can use zero-copy tensor transfer via /dev/shm and CUDA IPC.
  • sealed_worker: Fully isolated child with its own interpreter. No host sys.path reconstruction, JSON-RPC tensor transport only.

And two environment backends:

  • uv (default): Fast pip-compatible virtual environments.
  • conda: pixi-backed conda environments for packages that need conda-forge.
# Sealed worker with conda environment
config = pyisolate.ExtensionConfig(
    name="weather_processor",
    module_path="./extensions/weather",
    isolated=True,
    execution_model="sealed_worker",
    package_manager="conda",
    share_torch=False,
    conda_channels=["conda-forge"],
    conda_dependencies=["eccodes", "cfgrib"],
    dependencies=["xarray", "cfgrib"],
)

Implementing an Adapter

Applications integrate via the IsolationAdapter protocol:

from pyisolate.interfaces import IsolationAdapter

class MyAppAdapter(IsolationAdapter):
    @property
    def identifier(self) -> str:
        return "myapp"

    def get_path_config(self, module_path: str) -> dict:
        return {
            "preferred_root": "/path/to/myapp",
            "additional_paths": ["/path/to/myapp/extensions"],
        }

    def register_serializers(self, registry) -> None:
        registry.register(
            "MyCustomType",
            serializer=lambda obj: {"data": obj.data},
            deserializer=lambda d: MyCustomType(d["data"]),
        )

    def provide_rpc_services(self) -> list:
        return [MyRegistry, MyProgressReporter]

Architecture

┌─────────────────────┐     RPC      ┌─────────────┐
│    Host Process     │◄────────────►│ Extension A │
│                     │              │  (venv A)   │
│  ┌──────────────┐   │              └─────────────┘
│  │   Shared     │   │     RPC      ┌─────────────┐
│  │ Singletons   │   │◄────────────►│ Extension B │
│  └──────────────┘   │              │  (venv B)   │
└─────────────────────┘              └─────────────┘

Features

Core

  • Automatic virtual environment management
  • Bidirectional JSON-RPC over Unix Domain Sockets (no pickle)
  • Full async/await support
  • Lifecycle hooks: before_module_loaded(), on_module_loaded(), stop()
  • Error propagation across process boundaries

Advanced

  • Bubblewrap sandbox with deny-by-default filesystem (Linux)
  • CUDA wheel resolution for custom GPU package builds
  • Zero-copy tensor transfer via CUDA IPC and /dev/shm
  • Performance tracing (PYISOLATE_TRACE_FILE)
  • Multi-distro sandbox detection (RHEL, Ubuntu, Arch, SELinux)

Environment Variables

Variable Description
PYISOLATE_CHILD Set to "1" in isolated child processes
PYISOLATE_DEBUG_RPC "1" for verbose RPC message logging
PYISOLATE_TRACE_FILE Path for structured performance trace output
PYISOLATE_ENABLE_CUDA_IPC "1" to enable CUDA IPC tensor transport
PYISOLATE_PATH_DEBUG "1" for detailed sys.path logging during child init

Development

# Setup development environment
uv venv && source .venv/bin/activate
uv pip install -e ".[dev,test]"
pre-commit install

# Run tests
pytest

# Run linting
ruff check pyisolate tests

# Run benchmarks
python benchmarks/simple_benchmark.py

Use Cases

pyisolate is designed for:

  • Plugin Systems: When plugins may require conflicting dependencies
  • ML Pipelines: Different models requiring different library versions
  • Microservices in a Box: Multiple services with different dependencies in one app
  • Legacy Code Integration: Wrapping legacy code with specific dependency requirements

License

pyisolate is licensed under the MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyisolate-0.10.2.tar.gz (160.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyisolate-0.10.2-py3-none-any.whl (91.0 kB view details)

Uploaded Python 3

File details

Details for the file pyisolate-0.10.2.tar.gz.

File metadata

  • Download URL: pyisolate-0.10.2.tar.gz
  • Upload date:
  • Size: 160.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyisolate-0.10.2.tar.gz
Algorithm Hash digest
SHA256 c5803c0350ed773d1bcfed9cfb414b7b04a932c141e4a851d633d98a349f3b48
MD5 e186c16fb0d81f9a13b207a9bd046ed6
BLAKE2b-256 5470a749f8aa1e13db2bc39b1d75967fa60fdf103f6432a9662e760b8ffc23b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyisolate-0.10.2.tar.gz:

Publisher: build-wheels.yml on Comfy-Org/pyisolate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyisolate-0.10.2-py3-none-any.whl.

File metadata

  • Download URL: pyisolate-0.10.2-py3-none-any.whl
  • Upload date:
  • Size: 91.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyisolate-0.10.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b8471926f34625dee8acd8d037f3b1475847acd38983951cd27957987cf8514d
MD5 94f30c9c76a2f095f6f0ffd5e31077b9
BLAKE2b-256 92b1d76bda411b8ca87cc1dfea1da696996352fae8acbc7a8bea9a5eb4b388a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyisolate-0.10.2-py3-none-any.whl:

Publisher: build-wheels.yml on Comfy-Org/pyisolate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page