Python — in 5 Minuten zum ersten Sample
PyO3-Bindings für die DCPS-API + typisierte Topics aus zerodds-idlc generate --lang python + AsyncIO-Wrapper. abi3-Wheels für Python 3.9 und neuer. Der erzeugte Code ruft den XCDR-Codec in zerodds-wire.
5-Minuten-Quickstart
Ein virtualenv, eine Dependency, ~15 Zeilen Python.
1 · zerodds-py installieren
Das Paket zerodds ist auf PyPI und zieht zerodds-wire in derselben Version mit:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install zerodds==1.0.0rc7
Aus dem Source baut maturin die Erweiterung; vorher kommt die Wire-Runtime aus runtime/python:
git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install maturin
pip install ./runtime/python
cd crates/py
maturin develop --release --features extension-module
Wenn du nur die Runtime-Library (libzerodds.so) systemweit haben willst, kannst du das pre-built Paket nehmen:
# Ubuntu/Debian (amd64; arm64: _arm64.deb)
wget https://github.com/zero-objects/zero-dds/releases/download/v1.0.0-rc.7/zerodds-core_1.0.0-rc.7_amd64.deb
sudo dpkg -i zerodds-core_1.0.0-rc.7_amd64.deb
# Fedora/RHEL: die RPMs von rc.7 lassen sich nicht installieren (zerodds-core verlangt libzerodds.so()(64bit), das kein Paket bereitstellt); aus der Quelle bauen, siehe User Guide
# Arch Linux — AUR
yay -S zerodds-bin
Die Pakete liefern libzerodds.so, die zerodds.loader über ctypes lädt. Für macOS und Windows gibt es kein vorgebautes Paket mit libzerodds; libzerodds.dylib und zerodds.dll entstehen mit cargo build --release -p zerodds-c-api. Die PyO3-Erweiterung aus dem PyPI-Paket bringt den DDS-Stack selbst mit.
2 · Pub/Sub-Roundtrip (hello.py)
import zerodds
factory = zerodds.DomainParticipantFactory.instance()
participant = factory.create_participant(0)
topic = participant.create_bytes_topic("Chatter")
publisher = participant.create_publisher()
subscriber = participant.create_subscriber()
writer = publisher.create_bytes_writer(topic)
reader = subscriber.create_bytes_reader(topic)
writer.wait_for_matched_subscription(1, timeout_secs=5.0)
reader.wait_for_matched_publication(1, timeout_secs=5.0)
writer.write(b"hello")
reader.wait_for_data(timeout_secs=3.0)
for payload in reader.take():
print(f"got: {payload!r}")
▶ Runnable example: python-hello-bytes
3 · Laufen
python hello.py
# got: b'hello'
Installation
Aus PyPI
pip install zerodds==1.0.0rc7
Zieht zerodds-wire 1.0.0rc7 mit. Wheels für Linux x86_64/aarch64, macOS arm64 und Windows x86_64; ein abi3-Wheel pro Plattform. Das Paket verlangt Python 3.9 oder neuer.
Aus dem Source (Dev)
git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/py
python3 -m venv .venv
source .venv/bin/activate
pip install maturin pytest
pip install ../../runtime/python
maturin develop --features extension-module
pytest python/tests/
Voraussetzungen
- Python 3.9 oder höher; der Code aus
zerodds-idlc generate --lang pythonbraucht 3.10 oder höher. - Bei Build-aus-Source: Rust 1.97+ (siehe Dev-Install) + Xcode-CLT (macOS) bzw.
build-essential(Linux). - Aus-Source kompiliert ~30-60s auf einem 8-Core; aus PyPI <5s.
Typisierte Messages — zerodds-idlc generate --lang python
Typen kommen aus IDL. zerodds-idlc generate --lang python schreibt eine Dataclass je Typ, ihren Codec über zerodds_wire und ZD_TOPIC_DESCRIPTORS; zerodds.IdlTopic nimmt einen Eintrag daraus. Den Decorator @idl_struct (zerodds.idl) und zerodds.cdr gibt es nicht mehr. Der erzeugte Code braucht Python 3.10 oder neuer.
IDL (temperature.idl)
module sensor_msgs {
module msg {
struct Temperature {
long celsius;
string sensor_id;
sequence<octet> raw_blob;
};
};
};
Codegen + Nutzen
zerodds-idlc generate --lang python --out . temperature.idl
# schreibt ./temperature.py
import zerodds
from temperature import ZD_TOPIC_DESCRIPTORS
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = zerodds.IdlTopic(p, "Temp", ZD_TOPIC_DESCRIPTORS["sensor_msgs::msg::Temperature"])
Temperature = topic.cls
writer = topic.create_writer(p.create_publisher())
reader = topic.create_reader(p.create_subscriber())
writer.wait_for_matched_subscription(1, 5.0)
reader.wait_for_matched_publication(1, 5.0)
writer.write(Temperature(celsius=23, sensor_id="A7", raw_blob=[]))
reader.wait_for_data(3.0)
for msg in reader.take():
print(msg)
# sensor_msgs.msg.Temperature(celsius=23, sensor_id='A7', raw_blob=[])
▶ Runnable example: python-idl-struct
Was Python im Typ nicht ausdrücken kann (Breite einer Ganzzahl, Grenze eines Strings oder einer Sequenz), steht als typing.Annotated-Metadaten in der erzeugten Klasse; typing.get_type_hints(cls, include_extras=True) liest es zurück.
AsyncIO
Für async-fokussierte Apps gibt's zerodds.aio-Wrapper. Alle wait_*/write-Calls laufen über asyncio.to_thread; Event-Loop bleibt unblockiert.
import asyncio
import zerodds
from zerodds import aio as zaio
async def main():
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = p.create_bytes_topic("Chatter")
writer = zaio.AsyncBytesWriter(p.create_publisher().create_bytes_writer(topic))
reader = zaio.AsyncBytesReader(p.create_subscriber().create_bytes_reader(topic))
await writer.wait_for_matched_subscription(1, 5.0)
await reader.wait_for_matched_publication(1, 5.0)
await writer.write(b"async hello")
await reader.wait_for_data(3.0)
for payload in reader.take():
print(payload)
asyncio.run(main())
▶ Runnable example: python-aio
Klassen: AsyncBytesWriter, AsyncBytesReader, AsyncShapeWriter, AsyncShapeReader, AsyncWaitSet. Implementation: crates/py/python/zerodds/aio.py
QoS-Builder — alle 22 Policies
Statt Default-QoS kannst du jeden der 22 Policies setzen. Pattern: QosBuilder.set_X(...), dann create_*_writer_with_qos(topic, qos).
import zerodds
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = p.create_bytes_topic("Setpoint")
# State-Topic mit Late-Joiner-Cache (siehe QoS Cookbook §2)
qos = zerodds.DataWriterQos()
qos.set_reliability("Reliable", 0.1)
qos.set_durability("TransientLocal")
qos.set_history("KeepLast", 1)
writer = p.create_publisher().create_bytes_writer_with_qos(topic, qos)
▶ Runnable example: python-qos-writer
Verfügbare Setter (auswahl): set_reliability, set_durability, set_history, set_deadline, set_lifespan, set_latency_budget, set_liveliness, set_ownership, set_ownership_strength, set_partition, set_presentation, set_destination_order, set_resource_limits, set_transport_priority, set_writer_data_lifecycle, set_user_data, set_topic_data, set_group_data, set_durability_service.
Vollständige Reference: QoS Reference.
Tests & CI
Im Repo unter crates/py/python/tests/ liegen die pytest-Tests. Lauf:
cd crates/py
maturin develop --features extension-module
pytest python/tests/ -v
Conditional-Skips:
test_loader_smoke.py— skippt ohne gebautelibzerodds.so. Aktivieren:cargo build -p zerodds-c-api && ZERODDS_LIB=$PWD/../../target/debug/libzerodds.so pytest …test_shapesdemo_interop.py— skippt ohneddsperfim PATH (Cyclone DDS installieren für Cross-Vendor-Smoke).tests/ros2/— skippt ohneROS_DISTRO + RMW_IMPLEMENTATION=rmw_zerodds_shim.
CI-Pattern: GitHub Actions / GitLab CI mit maturin develop-Step plus pytest.
Python — first sample in 5 minutes
PyO3 bindings for the DCPS API + typed topics from zerodds-idlc generate --lang python + an AsyncIO wrapper. abi3 wheels for Python 3.9 and newer. The generated code calls the XCDR codec in zerodds-wire.
5-minute quickstart
A virtualenv, one dependency, ~15 lines of Python.
1 · Install zerodds-py
The zerodds package is on PyPI and pulls in zerodds-wire of the same version:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install zerodds==1.0.0rc7
From source, maturin builds the extension; the wire runtime from runtime/python goes in first:
git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install maturin
pip install ./runtime/python
cd crates/py
maturin develop --release --features extension-module
If you only want the runtime library (libzerodds.so) system-wide, you can take the pre-built package:
# Ubuntu/Debian (amd64; arm64: _arm64.deb)
wget https://github.com/zero-objects/zero-dds/releases/download/v1.0.0-rc.7/zerodds-core_1.0.0-rc.7_amd64.deb
sudo dpkg -i zerodds-core_1.0.0-rc.7_amd64.deb
# Fedora/RHEL: the rc.7 RPMs cannot be installed (zerodds-core requires libzerodds.so()(64bit), which no package provides); build from source, see the User Guide
# Arch Linux — AUR
yay -S zerodds-bin
The packages provide libzerodds.so, which zerodds.loader loads through ctypes. For macOS and Windows there is no pre-built package with libzerodds; libzerodds.dylib and zerodds.dll come from cargo build --release -p zerodds-c-api. The PyO3 extension from the PyPI package carries the DDS stack itself.
2 · Pub/sub roundtrip (hello.py)
import zerodds
factory = zerodds.DomainParticipantFactory.instance()
participant = factory.create_participant(0)
topic = participant.create_bytes_topic("Chatter")
publisher = participant.create_publisher()
subscriber = participant.create_subscriber()
writer = publisher.create_bytes_writer(topic)
reader = subscriber.create_bytes_reader(topic)
writer.wait_for_matched_subscription(1, timeout_secs=5.0)
reader.wait_for_matched_publication(1, timeout_secs=5.0)
writer.write(b"hello")
reader.wait_for_data(timeout_secs=3.0)
for payload in reader.take():
print(f"got: {payload!r}")
▶ Runnable example: python-hello-bytes
3 · Run
python hello.py
# got: b'hello'
Installation
From PyPI
pip install zerodds==1.0.0rc7
Pulls in zerodds-wire 1.0.0rc7. Wheels for Linux x86_64/aarch64, macOS arm64 and Windows x86_64; one abi3 wheel per platform. The package requires Python 3.9 or newer.
From source (dev)
git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/py
python3 -m venv .venv
source .venv/bin/activate
pip install maturin pytest
pip install ../../runtime/python
maturin develop --features extension-module
pytest python/tests/
Prerequisites
- Python 3.9 or higher; the code from
zerodds-idlc generate --lang pythonneeds 3.10 or higher. - For a build from source: Rust 1.97+ (see Dev Install) + Xcode CLT (macOS) or
build-essential(Linux). - From source it compiles in ~30-60s on an 8-core; from PyPI <5s.
Typed messages — zerodds-idlc generate --lang python
Types come from IDL. zerodds-idlc generate --lang python writes a dataclass per type, its codec over zerodds_wire and ZD_TOPIC_DESCRIPTORS; zerodds.IdlTopic takes one entry of it. The @idl_struct decorator (zerodds.idl) and zerodds.cdr are gone. The generated code needs Python 3.10 or newer.
IDL (temperature.idl)
module sensor_msgs {
module msg {
struct Temperature {
long celsius;
string sensor_id;
sequence<octet> raw_blob;
};
};
};
Codegen + use
zerodds-idlc generate --lang python --out . temperature.idl
# writes ./temperature.py
import zerodds
from temperature import ZD_TOPIC_DESCRIPTORS
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = zerodds.IdlTopic(p, "Temp", ZD_TOPIC_DESCRIPTORS["sensor_msgs::msg::Temperature"])
Temperature = topic.cls
writer = topic.create_writer(p.create_publisher())
reader = topic.create_reader(p.create_subscriber())
writer.wait_for_matched_subscription(1, 5.0)
reader.wait_for_matched_publication(1, 5.0)
writer.write(Temperature(celsius=23, sensor_id="A7", raw_blob=[]))
reader.wait_for_data(3.0)
for msg in reader.take():
print(msg)
# sensor_msgs.msg.Temperature(celsius=23, sensor_id='A7', raw_blob=[])
▶ Runnable example: python-idl-struct
What Python cannot express in a type (the width of an integer, the bound of a string or a sequence) is written as typing.Annotated metadata on the generated class; typing.get_type_hints(cls, include_extras=True) reads it back.
AsyncIO
For async-focused apps there's a zerodds.aio wrapper. All wait_*/write calls run over asyncio.to_thread; the event loop stays unblocked.
import asyncio
import zerodds
from zerodds import aio as zaio
async def main():
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = p.create_bytes_topic("Chatter")
writer = zaio.AsyncBytesWriter(p.create_publisher().create_bytes_writer(topic))
reader = zaio.AsyncBytesReader(p.create_subscriber().create_bytes_reader(topic))
await writer.wait_for_matched_subscription(1, 5.0)
await reader.wait_for_matched_publication(1, 5.0)
await writer.write(b"async hello")
await reader.wait_for_data(3.0)
for payload in reader.take():
print(payload)
asyncio.run(main())
▶ Runnable example: python-aio
Classes: AsyncBytesWriter, AsyncBytesReader, AsyncShapeWriter, AsyncShapeReader, AsyncWaitSet. Implementation: crates/py/python/zerodds/aio.py
QoS builder — all 22 policies
Instead of the default QoS you can set any of the 22 policies. Pattern: QosBuilder.set_X(...), then create_*_writer_with_qos(topic, qos).
import zerodds
factory = zerodds.DomainParticipantFactory.instance()
p = factory.create_participant(0)
topic = p.create_bytes_topic("Setpoint")
# state topic with a late-joiner cache (see QoS Cookbook §2)
qos = zerodds.DataWriterQos()
qos.set_reliability("Reliable", 0.1)
qos.set_durability("TransientLocal")
qos.set_history("KeepLast", 1)
writer = p.create_publisher().create_bytes_writer_with_qos(topic, qos)
▶ Runnable example: python-qos-writer
Available setters (selection): set_reliability, set_durability, set_history, set_deadline, set_lifespan, set_latency_budget, set_liveliness, set_ownership, set_ownership_strength, set_partition, set_presentation, set_destination_order, set_resource_limits, set_transport_priority, set_writer_data_lifecycle, set_user_data, set_topic_data, set_group_data, set_durability_service.
Full reference: QoS Reference.
Tests & CI
In the repo under crates/py/python/tests/ are the pytest tests. Run:
cd crates/py
maturin develop --features extension-module
pytest python/tests/ -v
Conditional skips:
test_loader_smoke.py— skipped without a builtlibzerodds.so. Enable:cargo build -p zerodds-c-api && ZERODDS_LIB=$PWD/../../target/debug/libzerodds.so pytest …test_shapesdemo_interop.py— skipped withoutddsperfin PATH (install Cyclone DDS for the cross-vendor smoke).tests/ros2/— skipped withoutROS_DISTRO + RMW_IMPLEMENTATION=rmw_zerodds_shim.
CI pattern: GitHub Actions / GitLab CI with a maturin develop step plus pytest.