Skip to main content

pympacds

PyPI version PyPI downloads Python versions License: MIT CI

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

Using PIP

pip install pympacds

For minimal embedded deployments without the optional Cython extension:

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

Note: using pip doesn't install the system configurations files (it requires admin privileges to save D-Bus configurations). In order to work run sudo pympacds-admin setup before running services.

Using PPA

Debian packages are provided through launchpad ppa (dargor0/mpacds):

sudo add-apt-repository ppa:dargor0/mpacds
sudo apt update
sudo apt install python3-pympacds

Packages are installed system wide with all configurations and resource files (no need to do a setup step).

Repository has been tested on Ubuntu (plucky, resolute, stonking) and Debian (stable, testing, unstable).

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

Changelog

Release notes are published on the releases page.

License

MIT

Metadata

Release files for pympacds 0.3.2

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.2
File Size Uploaded
pympacds-0.3.2.tar.gz 84.7 kB Details

Built distribution (wheel)

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

Total release size: 136.0 kB

Release files / pympacds-0.3.2.tar.gz

Download URL pympacds-0.3.2.tar.gz
Size 84.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3632b8983058d92322099d123b994e447b9fd9cc133baf6ff7619cc3ef0a31bb
BLAKE2b-256 checksum
How to use checksums
c09467bdd87da598b7d0702392c30c87a9d25799e3bd56c2d33660f6aa61b7fc
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.2-py3-none-any.whl

Download URL pympacds-0.3.2-py3-none-any.whl
Size 51.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
606028f143b339024615593c526a86f115b8ed987bf1a33412b7515a639f442a
BLAKE2b-256 checksum
How to use checksums
10c158eaf43e44bee1b892e8a432535209445a8b04c128698497a25b12253a95
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

This release

0.3.2 This release

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

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