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 (e.g. HTTP config provisioning).

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.1.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.1.0
File Size Uploaded
pympacds-0.1.0.tar.gz 41.4 kB Details

Built distribution (wheel)

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

Total release size: 67.6 kB

Release files / pympacds-0.1.0.tar.gz

Download URL pympacds-0.1.0.tar.gz
Size 41.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ba7c2f1fb630bd39ff08ed2ed2d750f0db4f20ec461d9cf4073ece03709b74ed
BLAKE2b-256 checksum
How to use checksums
6abd755d5d77ea54aca188a64d6074fe06c456567486999275c542cdb7fe1b53
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.1.0-py3-none-any.whl

Download URL pympacds-0.1.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4f47928d303257db7c2854c33d7396412af75f6659ed6f8ee6b1f7dee0561eec
BLAKE2b-256 checksum
How to use checksums
9463ff9f982989b1cc48189b4ad7d24f64d6305ca650182551eb42b33b877ab8
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

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.0 This release

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