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.2.1

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.2.1
File Size Uploaded
pympacds-0.2.1.tar.gz 61.4 kB Details

Built distribution (wheel)

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

Total release size: 99.5 kB

Release files / pympacds-0.2.1.tar.gz

Download URL pympacds-0.2.1.tar.gz
Size 61.4 kB
Tags Source
SHA-256 checksum
How to use checksums
cee0d54be2ef69916ccd47c7547d8196de8ca42389540ce3e420c50f99311b23
BLAKE2b-256 checksum
How to use checksums
1640f1c1ddb97cd44335cebcc232f90ffc52701f3a396654f1b4180eb2ad307a
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.2.1-py3-none-any.whl

Download URL pympacds-0.2.1-py3-none-any.whl
Size 38.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5cf445527601f53b861cb75b120a68498a9dfdee9f07825927d308072ce074f3
BLAKE2b-256 checksum
How to use checksums
0543efb09724ae3f831fb1c86c761d039d00b83e428417ed69cc22acf1758b3d
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

This release

0.2.1 This release

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