A Python client for dflockd — a distributed FIFO lock and counting-semaphore server.
- Sync and async clients — pick the one that matches your runtime
- Distributed locks and counting semaphores with FIFO ordering
- Single-phase
acquireand two-phaseenqueue+wait - Background lease renewal — call
acquire, hold for as long as you need - Grant tokens carry a monotonic fence prefix — usable as fencing tokens
- Multi-server sharding (deterministic CRC-32; matches the Go and TypeScript clients)
- TLS and shared-secret authentication
- Zero runtime dependencies; Python 3.12+
pip install dflockd-client
# or
uv add dflockd-clientA running dflockd server on
127.0.0.1:6388 is the only prerequisite.
from dflockd_client import SyncDistributedLock
with SyncDistributedLock("my-key") as lock:
# critical section — lease auto-renews in a daemon thread
print(f"acquired: {lock.token}")import asyncio
from dflockd_client import AsyncDistributedLock
async def main():
async with AsyncDistributedLock("my-key") as lock:
print(f"acquired: {lock.token}")
asyncio.run(main())Up to limit concurrent holders on the same key:
from dflockd_client import SyncDistributedSemaphore
with SyncDistributedSemaphore("pool", limit=3) as sem:
print(f"slot: {sem.token}")import ssl
from dflockd_client import SyncDistributedLock
with SyncDistributedLock(
"my-key",
auth_token="shared-secret",
ssl_context=ssl.create_default_context(),
) as lock:
...from dflockd_client import SyncDistributedLock
with SyncDistributedLock(
"my-key",
servers=[("a", 6388), ("b", 6388), ("c", 6388)],
) as lock:
# the same key always routes to the same server
...Every grant returns a 32-char hex token whose first 16 hex chars are a
monotonic uint64 (big-endian) that strictly increases on every grant from
a server. fence_from_token parses it, so the token doubles as a
fencing token:
a downstream resource stores the highest fence it has seen for a key and
rejects any write whose fence compares less.
from dflockd_client import SyncDistributedLock, fence_from_token
with SyncDistributedLock("row:42") as lock:
fence = fence_from_token(lock.token) # int — pass to your DB / blob storeSee the docs for two-phase acquisition, exception handling, low-level transport, and more.