Skip to main content

Wetlands

Wetlands tests Wetlands PyPI Wetlands Python versions

Wetlands is a Python library for creating isolated environments with Pixi and running Python functions inside them.

This lets an application use libraries with incompatible dependencies at the same time. For example, Cellpose and StarDist can each run in their own environment while exchanging ordinary Python values and NumPy arrays with the main application.

Wetlands creates these environments when needed, installs their dependencies, keeps worker processes ready for repeated calls, and cleans up their resources automatically. It can be used in desktop applications, servers, and plugin systems.

Wetlands is intended for code you trust. Isolated environments prevent dependency conflicts, but they do not restrict what code can access on your computer.

Appose is an alternative for applications that need interprocess cooperation across Python, Java, or Groovy, including explicit zero-copy tensor sharing between languages. Wetlands is focused on running Python functions and adds automatic NumPy transport, managed worker pools, and post-hoc debugger attachment. See Wetlands and Appose for a short comparison, or visit the Appose documentation.

Wetlands 2 provides:

  • side-effect-light manager construction;
  • observable and cancellable preparation and provisioning operations;
  • reproducible Pixi projects and pixi.lock files;
  • managed-environment discovery and safe asynchronous removal;
  • warm worker pools;
  • validated environment variables for individual worker indices;
  • qualified installed-package targets and path targets for local development;
  • automatic transport of ordinary Python values and NumPy arrays;
  • blocking, callback-based, and asyncio-friendly execution.

The first preparation may download a verified Pixi executable, and the first provisioning of an environment downloads its declared packages. These operations require network access and can take several minutes. Wetlands stores Pixi, managed environments, locks, and runtime state below the manager root you choose.

Installation

pip install wetlands

Install the optional host-side NumPy dependency when arrays cross the execution boundary:

pip install "wetlands[shared-memory]"

Quick start

The manager constructor only validates and stores configuration. Downloading or inspecting Pixi begins when prepare() or provision() is called.

import numpy as np

from wetlands import EnvironmentManager, EnvironmentSpec

manager = EnvironmentManager(root="wetlands")

preparation = manager.prepare()
preparation.listen(lambda event: print(event.stage, event.message))
pixi = preparation.wait_for()

spec = EnvironmentSpec(
    python="3.12.*",
    conda=("numpy>=2",),
)
environment = manager.provision("numpy-example", spec).wait_for()

with environment.start(workers=1) as workers:
    image = np.arange(9, dtype=np.float32).reshape(3, 3)
    task = workers.submit_import(
        "numpy:negative",
        args=(image,),
    )
    result = task.wait_for()

np.testing.assert_array_equal(result, -image)
manager.close()

This example is self-contained: Pixi installs NumPy in the worker environment, and the qualified target imports NumPy inside that environment. Your own worker package exposes ordinary Python functions, is declared in EnvironmentSpec, and is called by its installed module:qualified.callable name in the same way.

Wetlands owns the shared-memory details. Inputs use copy-in semantics and returned arrays are independently owned by the caller. The repository also contains a complete local worker-package example.

Async applications

Preparation, provisioning, and execution objects are awaitable. Their events() methods expose async event streams while the caller retains ownership of its event loop.

import asyncio

from wetlands import EnvironmentManager, EnvironmentSpec


async def main() -> None:
    manager = EnvironmentManager(root="wetlands")
    try:
        preparation = manager.prepare()
        async for event in preparation.events():
            print(event.kind.value, event.message)
        await preparation

        environment = await manager.provision(
            "analysis",
            EnvironmentSpec(python="3.12.*", conda=("numpy",)),
        )

        workers = await asyncio.to_thread(environment.start, workers=2)
        try:
            task = workers.submit_import(
                "numpy:negative",
                args=([1.0, 2.0, 3.0],),
            )
            result = await task
            print(result)
        finally:
            await asyncio.to_thread(workers.close)
    finally:
        await asyncio.to_thread(manager.close)


asyncio.run(main())

Starting, attaching, detaching, and closing worker pools, and closing a manager, are blocking lifecycle calls. Async applications should run those calls with asyncio.to_thread() as shown above.

Cancel an operation or execution task with cancel(). A canceled provisioning operation becomes terminal only after its active process tree has stopped and its incomplete environment has been cleaned up. For a running worker task, Wetlands first requests cooperative cancellation. If the worker does not finish during the configured grace period, Wetlands terminates its process tree and starts a replacement worker.

Pixi projects and lockfiles

EnvironmentSpec is the complete managed recipe:

from pathlib import Path

from wetlands import EnvironmentSpec, LocalPackage, PostInstallCommand

spec = EnvironmentSpec(
    python="3.12.*",
    conda=("numpy>=2", "scikit-image", "pip"),
    pypi=("example-pypi-package==1.2.0",),
    channels=("conda-forge",),
    local=(LocalPackage(Path("../worker-package"), editable=True),),
    post_install=(PostInstallCommand(("python", "-m", "worker_package.prepare_assets")),),
    pixi_lock=Path("pixi.lock"),
)

When pixi_lock is supplied, Wetlands provisions from those exact locked dependencies. If the recipe contains local packages, the supplied lockfile must already resolve those same local sources and editable settings. It must also include Wetlands' exact managed worker-runtime dependencies, including its debugpy pin. Without one, Pixi resolves the generated project and Wetlands preserves the resulting lockfile in the managed environment.

Wetlands owns the managed debugpy version, so applications must not declare it in EnvironmentSpec. The managed runtime pin participates in recipe identity and causes environments to rebuild when it changes.

An environment is ready only after every installation and validation step succeeds and Wetlands atomically publishes its ready metadata. Failed, canceled, or crash-interrupted provisioning is rebuilt on the next attempt rather than resumed. The returned ManagedEnvironment exposes its canonical project and lockfile paths, Pixi executable and version, recipe hash, lockfile hash, and generation ID.

Worker targets

Installed packages use a qualified target:

task = workers.submit_import(
    "package.module:ClassName.method",
    args=(value,),
)

The module is imported inside the isolated worker.

Local development can use an explicit source path:

task = workers.submit_path(
    "worker_code.py",
    "segment",
    kwargs={"image": image},
    cache=False,
)

Path targets are keyed by canonical path and content, so equal filename stems do not collide.

Debug running workers

Wetlands can start a debugger after an application and its workers are already running. No debug flag or debugger call is required in application or worker code.

wetlands workers --root ./wetlands --environment numpy-example
wetlands debug --root ./wetlands --environment numpy-example --worker WORKER_ID --editor vscode --source .

The debug adapter remains available for reconnection until its worker exits. See Debugging running workers and Persistent workers and reconnection.

Supported values

Execution arguments and results may contain:

  • None, booleans, integers, floats, strings, and bytes;
  • nested lists, tuples, and dictionaries with simple keys;
  • NumPy arrays without object dtype.

Unsupported objects fail explicitly at the boundary. Non-contiguous arrays are transported as contiguous arrays. Intermediate task outputs are limited to simple values in Wetlands 2.

Migration from Wetlands 1

Wetlands 2 is a major release with a deliberately smaller public API. Applications should migrate explicitly instead of relying on compatibility shims.

See the Wetlands 2 migration guide.

Development

Install the development environment with:

uv sync --frozen --group dev --extra shared-memory

Run the fast test suite with:

uv run --extra shared-memory pytest -m "not integration and not compat and not manual"

Run the representative real-Pixi integration suite with:

UV_PROJECT_ENVIRONMENT=.venv-py314 uv run --python 3.14 --extra shared-memory pytest tests/test_v2_pixi_integration.py

Run linting with:

uv run ruff check
uv run ruff format --check
uv run mypy src/wetlands

Build the package with:

uv build

Documentation

The complete documentation is available at arthursw.github.io/wetlands. Contributor-facing architecture and codec boundaries are described in the developer guide.

License

Wetlands is licensed under the MIT License.

See the security policy before executing third-party worker code or post-install commands.

Download files

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

Source Distribution

wetlands-2.2.0.tar.gz (281.1 kB view details)

Uploaded Source

Built Distribution

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

wetlands-2.2.0-py3-none-any.whl (114.8 kB view details)

Uploaded Python 3

File details

Details for the file wetlands-2.2.0.tar.gz.

File metadata

  • Download URL: wetlands-2.2.0.tar.gz
  • Upload date:
  • Size: 281.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for wetlands-2.2.0.tar.gz
Algorithm Hash digest
SHA256 493ba5e25abb99520dfa1cea0ef0ea7be632c6279849bf61ecb122ebad7b9531
MD5 5503b8c8266b19416ffba6226f3a3244
BLAKE2b-256 d7570d6c8a3bb64876aa8035b13f6bad04cec749fe9b72e8ef9fc14910be62b7

See more details on using hashes here.

File details

Details for the file wetlands-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: wetlands-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 114.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for wetlands-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cad0f4488354cde8892466c8857c0f09618b0a3b5df81838bf0fbf93b2ea498f
MD5 43476e40ca2c27fd0334016d4b6e1f41
BLAKE2b-256 e580b0174282bd5834c2424b76f5682eb1cb2667a461d74652aff5bd9b6abb4e

See more details on using hashes here.

Release history Release notifications | RSS feed

2.4.0

2 files

2.3.3

2 files

2.3.2

2 files

2.3.1

2 files

2.3.0

2 files

This release

2.2.0 This release

2 files

2.1.0

2 files

2.0.0

2 files

1.1.6

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.9

2 files

1.0.8

2 files

1.0.7

2 files

1.0.5

2 files

1.0.4

2 files

1.0.3

2 files

1.0.1

2 files

1.0.0

2 files

0.4.11

2 files

0.4.10

2 files

0.4.8

2 files

0.4.7

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.0

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

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