Eclipse Zenoh Python API
Eclipse Zenoh (pronounce /zeno/) is a lightweight, high-performance middleware that unifies data in motion, data at rest, and computations across diverse environments, from embedded systems to the cloud. The Python API (version 1.9.0) provides bindings to the core Rust implementation, enabling pub/sub, geo-distributed storage, queries, and computations. It maintains an active development and release cadence, with major updates often quarterly, aiming for performance and efficiency beyond mainstream stacks.
Common errors
-
AttributeError: 'NoneType' object has no attribute 'timestamp' (or similar on sample.data_info)
cause In older Zenoh Python API versions, `data_info` or `timestamp` might not always be present or valid on a received `Sample` object, leading to `NoneType` errors when accessed directly without checks. The API for `Sample` payload handling has evolved.fixFor Zenoh 1.x, access the payload directly via `sample.payload`. To get string representation, use `sample.payload.to_string()`. If specific metadata is expected, ensure the publishing side includes it and check for its presence on the receiving side. -
ERROR zenoh::net::routing::pubsub] Error treating timestamp for received Data (incoming timestamp ... exceeding delta 100ms is rejected: ...)
cause This error indicates that the system clocks between the Zenoh publisher and subscriber/router are not synchronized, and the time difference exceeds 100 milliseconds.fixSynchronize the system clocks of all machines running Zenoh applications using a Network Time Protocol (NTP) client or Precision Time Protocol (PTP). -
Command 'rustc' not found
cause You are attempting to install `eclipse-zenoh` from a source distribution, but the Rust toolchain (including the `rustc` compiler) is not installed or not in your system's PATH.fixInstall the Rust toolchain by following the instructions at `https://rustup.rs/`. After installation, ensure your shell environment is updated (e.g., `source $HOME/.cargo/env`) and try `pip install eclipse-zenoh` again.
Warnings
- breaking The API underwent significant reworks between versions 0.x and 1.x (e.g., v0.11 to v1.0), emphasizing a more 'pythonic' feel. Key changes include mandatory use of context managers for sessions/entities, the `Value` type being replaced by `ZBytes` and `Encoding`, and `drop-callback` requiring wrapping in `handlers.Callback`.
- gotcha Installing `eclipse-zenoh` via pip might fail with build errors if you are on a platform without pre-built binary wheels and do not have a Rust toolchain installed. This is because the Python API is a binding over a Rust implementation.
- gotcha Failure to properly close a Zenoh session can lead to the script hanging on exit. This occurs if object finalizers are called after the library's internal Rust thread has already been killed.
- gotcha Zenoh nodes communicating with each other can drop messages or log 'Error treating timestamp for received Data' if their system clocks drift by more than 100ms.
Install
-
pip install eclipse-zenoh
Imports
- zenoh
import zenoh
- Config
import zenoh config = zenoh.Config()
- Session
import zenoh with zenoh.open(zenoh.Config()) as session:
- Publisher
publisher = session.declare_publisher(key)
- Subscriber
subscriber = session.declare_subscriber(key, listener)
- Sample
def listener(sample): ... print(sample.payload.to_string())
- ZBytes
value_bytes = zenoh.ZBytes(b'hello')
Quickstart
import zenoh
import time
import random
import os
# Configure a Zenoh session (default configuration for local peer/client)
# For a router or specific configuration, consider loading from a file:
# config_file = os.environ.get('ZENOH_CONFIG_FILE', '')
# if config_file: config = zenoh.Config.from_file(config_file)
# else: config = zenoh.Config()
def read_temp():
return random.randint(15, 30)
if __name__ == "__main__":
# Open a Zenoh session using a context manager for proper cleanup
with zenoh.open(zenoh.Config()) as session:
key = 'myhome/kitchen/temp'
# Declare a publisher on the specified key expression
pub = session.declare_publisher(key)
print(f"Zenoh Publisher sending data to '{key}'...")
try:
while True:
t = read_temp()
buf = f"{t}"
pub.put(buf)
print(f"Putting Data ('{key}': '{buf}')...")
time.sleep(1)
except KeyboardInterrupt:
print("Publisher stopped.")