Skip to main content

pympacds

Python Multi Process Async-based Cooperative Discoverable Services Framework

A lightweight, D-Bus-native application framework for building modular, multi-process, asyncio-based daemons on Linux — particularly suited for embedded and IoT systems.

Overview

pympacds provides a common foundation for building systems composed of multiple cooperating daemons that communicate via D-Bus. Each daemon runs as an independent process (managed by systemd as a service), uses Python's asyncio for internal concurrency, and automatically discovers peer services on the D-Bus system bus.

The framework is designed for any domain — IoT gateways, industrial control, home automation, automotive, robotics, or any Linux-based distributed system.

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    D-Bus System Bus                          │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │ Service A │  │ Service B │  │ Service C │  │ Service D │   │
│  │ (sensor)  │  │ (storage) │  │ (comm)    │  │ (ui)      │   │
│  │ ProcessBase│ │ ProcessBase│ │ ProcessBase│ │ ProcessBase│  │
│  │ DBusManager│ │ DBusManager│ │ DBusManager│ │ DBusManager│  │
│  │ task1      │ │ task1      │ │ task1      │ │ task1      │  │
│  │ task2      │ │ task2      │ │            │ │            │  │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │
│       │              │              │              │         │
│  discover ←────────→ discover ←────→ discover ←──→ discover │
│  (auto peer detection via NameOwnerChanged)                 │
└─────────────────────────────────────────────────────────────┘
                              │
                    ┌─────────┴──────────┐
                    │    systemd (PID 1)  │
                    │  service-a.service  │
                    │  service-b.service  │
                    │  service-c.service  │
                    └────────────────────┘

Features

pympacds provides:

  • Process lifecycle — ProcessBase with setup/init/main/close, structured logging, signal handling, and named task management.
  • D-Bus transport — DBusManager over dbus-fast, configurable namespace prefix, and graceful disconnect.
  • Service discovery — automatic peer detection and dynamic subscribe/unsubscribe between services.
  • Interface contracts — validated D-Bus interface definitions, with built-in Health, Lifecycle, Config, and Metrics contracts.
  • Middleware — optional lifecycle extensions (HTTP config provisioning, signal-action rules).

See Features and Philosophy for the full details.

Example: Minimal Service

import asyncio
import time
from pympacds.process import ProcessBase
from pympacds.dbus import DBusManager
from pympacds.contracts import ServiceContract, dbus_method, dbus_signal


class MyContract(ServiceContract):
    def __init__(self, ifname, base):
        super().__init__(ifname, base)
        self._require("dbus_my_method")

    @dbus_method()
    def my_method(self, arg: "s") -> "s":
        return self.base.dbus_my_method(arg)

    @dbus_signal()
    def heartbeat(self, uptime: "i") -> "i":
        return [uptime]


class MyService(ProcessBase):
    def __init__(self):
        super().__init__(
            name="myservice",
            version="1.0.0",
            description="A minimal pympacds service",
            bus_prefix="com.example.mysystem",
        )

    async def start_dbus(self):
        self.bus = DBusManager(
            logger=self.logger,
            busname="myservice",
            bus_prefix=self.bus_prefix,
        )
        self.iface = MyContract("com.example.MyInterface", self)
        self.bus.add_interface("MyService", self.iface)
        await self.bus.start()
        return True

    def update_tasks(self):
        if "periodic" not in self.tasklist:
            self.tasklist["periodic"] = asyncio.create_task(self._periodic(), name="periodic")

    def dbus_my_method(self, arg: str) -> str:
        return f"Got: {arg}"

    async def _periodic(self):
        try:
            while not self.exitevent.is_set():
                await self.do_waitexit(timeout=5)
                self.iface.heartbeat(int(time.time()))
        except asyncio.CancelledError:
            pass


MyService().start()

Installation

pip install pympacds

For minimal embedded deployments without the optional Cython extension:

SKIP_CYTHON=1 pip install --no-binary dbus-fast pympacds

Documentation

Detailed documentation lives in the doc/ directory:

Key Concepts

Concept Description
Service A single-purpose daemon that subclasses ProcessBase and exports a D-Bus interface
Bus D-Bus system bus used as the IPC backbone between services
Discovery Automatic peer detection via bus name conventions and NameOwnerChanged signals
Interface Contract A standardized D-Bus interface template that enforces required callbacks at construction time
Task An asyncio coroutine managed inside a service's event loop
Lifecycle setup → init_loop → main_loop → close_loop pattern inherited from ProcessBase

License

MIT

Metadata

Release files for pympacds 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pympacds 0.3.0
File Size Uploaded
pympacds-0.3.0.tar.gz 77.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pympacds 0.3.0
File Interpreter ABI Platform
pympacds-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 125.5 kB

Release files / pympacds-0.3.0.tar.gz

Download URL pympacds-0.3.0.tar.gz
Size 77.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e30330007e3d024a48cc158f16bc67d94ce5f76be59f0b158fcea2ddb5cc631e
BLAKE2b-256 checksum
How to use checksums
b6999a362a78f6d85b1b7eab766204f2e84d2f8724ea0a1aa6c2b981d50d60a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / pympacds-0.3.0-py3-none-any.whl

Download URL pympacds-0.3.0-py3-none-any.whl
Size 47.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b994bc9af3b75f30c867c30dc428e13ecaabe0592c269cb906fb7bdc0a6159b2
BLAKE2b-256 checksum
How to use checksums
e9ec762066f57d713944205829f2673350c04232dbdf985302393c61fd9bf569
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page