Each run of consecutive indices was its own uncached hyperslab read, so a list over a compressed chunked dataset decoded the same chunk once per run (d[range(0, 200000, 40)] over 20 gzip chunks: 8 s, h5py 0.014 s). Plan::reads now groups the indices — a group ends only where a whole chunk holds no selected index, or, unchunked, at a gap over 64 KiB — and the selected rows are gathered from each group's block in Rust. Now 3.8 ms (h5py 4.1 ms, release, tank). The new test (1-D, 2-D and contiguous, compared with h5py, 2 s bound) took 5.8 s before. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
clawhdf5-py
Python bindings for clawhdf5 — a pure-Rust HDF5 library. The package is
clawhdf5 (import clawhdf5); it needs numpy and no libhdf5.
Install
Not on PyPI yet. Build it into a virtualenv with maturin:
pip install maturin numpy
cd crates/clawhdf5-py
maturin develop --release
python -c "import clawhdf5; print(clawhdf5.__version__)"
Reading
The read API follows h5py:
import numpy as np
import clawhdf5
with clawhdf5.File("data.h5", "r") as f:
f.keys(), f["group"].items(), "group/data" in f
ds = f["group/data"] # or f["/group/data"], f["group"]["data"]
ds.shape, ds.dtype, ds.attrs["units"]
ds[10:20, ::2] # only the selected elements are read
ds[-1], ds[..., 0], ds[[1, 4, 7]]
np.asarray(ds)
f["table"]["id"] # a compound field
Dataset.dtypeis the numpy dtype h5py reports: integers and IEEE floats of every width in either byte order,bool, enums (withdtype.metadata['enum']), complex,S<n>fixed strings,objectfor variable-length strings (bytesvalues) and sequences (array values),V<n>opaque, array types, and compounds as structured dtypes. Other types raiseTypeError.- Keys are h5py's: integers, slices with a positive step,
..., one increasing list of integers, compound field names. Each maps onto a hyperslab selection.None, negative steps and boolean masks are refused with h5py's errors. - The bytes the library reads become the numpy array's buffer without a copy, and the read runs with the GIL released, so threads read in parallel.
- Attributes return what h5py returns;
clawhdf5.Emptystands for a null dataspace (h5py'sEmpty).
Writing
clawhdf5.File(path, "w") with create_dataset(name, data=array, chunks=..., compression="gzip"), create_group and attrs[...] = ...
writes float64, float32, int64, int32 and uint8 arrays; the file is
written on close().
Tests
pip install pytest h5py
pytest crates/clawhdf5-py/tests
tests/test_read_vs_h5py.py compares every read with h5py on a file h5py
writes. scripts/ci-test.sh builds the wheel and runs these in CI.
License
MIT