Tooz Coordination Library
Tooz is a Python library designed to provide distributed systems primitives such as group membership, leader election, distributed locking, and distributed messaging. It offers a unified API over various backend drivers like Redis, ZooKeeper, and Etcd. Currently at version 8.1.0, it is actively maintained as part of the OpenStack ecosystem with regular updates.
Common errors
-
tooz.drivers.NoDriverFound: No driver could be found for connection string 'redis://localhost:6379'.
cause The required backend driver package (e.g., 'redis') is not installed, or the connection string prefix does not match any available driver.fixEnsure the necessary driver extra is installed (e.g., `pip install tooz[redis]`). Verify the connection string format is correct for your chosen backend. -
ImportError: cannot import name 'CoordinationDriver' from 'tooz' (or similar for other classes)
cause `CoordinationDriver` and other core classes are not directly exposed under the top-level `tooz` package for newer versions. This import path might have worked in very old versions.fixImport `CoordinationDriver` from `tooz.coordination` (e.g., `from tooz.coordination import CoordinationDriver`). For new code, prefer `tooz.drivers.DriverFactory` as the main entry point. -
redis.exceptions.ConnectionError: Error connecting to server: [Errno 111] Connection refused.
cause The backend service (e.g., Redis server, Zookeeper ensemble, Etcd cluster) specified in the connection string is not running or is not accessible at the given host and port from your application's environment.fixEnsure the backend service is running and configured to accept connections from your application. Double-check the host, port, and any authentication details in your `tooz` connection string.
Warnings
- breaking Tooz versions 8.0.0 and above require Python 3.10 or newer. Older Python versions are no longer supported.
- gotcha Tooz drivers for specific backends (e.g., Redis, Zookeeper) are optional dependencies and must be installed separately using 'extras'. Installing just `pip install tooz` will only provide the core library and file/memory drivers.
- deprecated While `tooz.coordination.CoordinationDriver` is still available, `tooz.drivers.DriverFactory` is the recommended and more robust entry point for initializing drivers since `tooz` v7.0.0. Direct instantiation of specific drivers (e.g., `tooz.drivers.redis.RedisDriver`) is also less portable.
- gotcha Distributed locks obtained via `tooz` are not automatically released if the process crashes or loses connectivity without properly calling `driver.disconnect()` or `lock.release()`. Use `try...finally` blocks to ensure cleanup.
Install
-
pip install tooz -
pip install tooz[redis] -
pip install tooz[zookeeper]
Imports
- DriverFactory
from tooz.drivers import DriverFactory
- Lock
from tooz.locking import Lock
- CoordinationDriver
from tooz import CoordinationDriver
from tooz.coordination import CoordinationDriver
Quickstart
import os
import time
from tooz.drivers import DriverFactory
# Use a file-based driver for local testing or set an environment variable for a real backend
# e.g., export TOOZ_BACKEND="redis://localhost:6379/0" (for Redis DB 0)
# e.g., export TOOZ_BACKEND="zookeeper://localhost:2181"
connection_string = os.environ.get("TOOZ_BACKEND", "file:///tmp/tooz_locks_example")
# Group ID for coordination primitives, must be bytes
group_id = b"my_application_group"
driver = None
try:
# Initialize the driver factory. This will select the appropriate driver
# based on the connection string prefix (e.g., 'redis://', 'file://').
driver = DriverFactory(connection_string, group_id)
print(f"Connected to tooz backend: {connection_string}")
# Example: Acquire a distributed lock
lock_name = b"my_critical_section"
# `timeout` specifies how long to wait to acquire the lock.
# `heartbeat_timeout` specifies how often to renew the lock if acquired.
lock = driver.get_lock(lock_name, timeout=5, heartbeat_timeout=1)
print(f"Attempting to acquire lock '{lock_name.decode()}'...")
if lock.acquire():
print("Lock acquired successfully! Performing critical work...")
# Simulate some work
time.sleep(2)
print("Work done, releasing lock.")
# Lock is automatically released by the 'finally' block when driver disconnects
# or can be explicitly released with lock.release()
else:
print("Could not acquire lock within timeout.")
finally:
if driver:
# Ensure the driver is disconnected to release resources and locks.
driver.disconnect()
print("Disconnected from tooz backend.")