Set Up a Python Project#

The ovstage Python package binds the ovstage C data plane through ctypes, so the ovstage shared library must be loadable at import time. Programs use Stage and PathDictionary (both context managers) plus numpy for tensor attribute I/O.

Note

ovstage is pre-release. The examples consume ovstage as a published wheel using uv; if the pinned wheel cannot be resolved, the public wheel is not published yet.

Requirements#

  • Python 3.10–3.13 (requires-python = ">=3.10,<3.14"). Recreate the environment with a supported interpreter rather than editing the constraint.

  • NumPy, for tensor I/O (write_attribute(tensors=...), group.array(...)):

    pip install numpy
    

Making ovstage Importable#

Depend on the published ovstage wheel — for example a uv project that pins it in pyproject.toml (the pattern the examples/python projects use), then run with uv run. Alternatively, put the ovstage package on PYTHONPATH directly.

Loading the Shared Library#

The bindings load the ovstage shared library (ovstage.dll on Windows) the first time you construct a Stage or PathDictionary. The wheel bundles the library and its <package>/bin layout is searched automatically, so no extra setup is needed. If you are instead running against a locally built shared library, make it discoverable:

# Linux
export LD_LIBRARY_PATH=/path/to/ovstage/lib:$LD_LIBRARY_PATH
# Windows (PowerShell)
#   $env:PATH = "C:\path\to\ovstage\bin;$env:PATH"

Alternatively, set the OVSTAGE_LIBRARY_PATH_HINT environment variable.

Minimal Program#

# Write one float per prim into the "temperature" column at ordinal 1,
# seal it by advancing the write floor to 1, then read it back. Tensor
# data crosses as a numpy array (CPU) via DLPack; async ops return an
# Operation whose .wait() raises OvstageError on failure. The read is
# a context manager -- block exit releases its handle even when an
# error interrupts -- and the fetched group is released in a finally.
stage.write_attribute(
    query, attr, ordinal=1, tensors=np.array([1.0, 2.0, 3.0], np.float32), is_array=False
).wait()
stage.advance_write_floor(ordinal=1).wait()

with stage.read_attributes(query, [attr], OrdinalRange.latest(1)) as read:
    read.wait()
    group = read.fetch_next()
    if group is None:
        raise SystemExit("read returned no group at ordinal 1")
    try:
        # group.array(i) is a zero-copy numpy view of tensor i (CPU).
        print("read back ordinal", group.ordinal, group.array(0))  # -> [1. 2. 3.]
    finally:
        stage.release_group(group)

Where to Go Next#