This guide will help you get started with py-key-value, from installation to basic usage patterns.
Install the async library:
pip install py-key-value-aio
Install with specific backend support:
# Redis support
pip install py-key-value-aio[redis]
# DynamoDB support
pip install py-key-value-aio[dynamodb]
# Elasticsearch support
pip install py-key-value-aio[elasticsearch]
# MongoDB support
pip install py-key-value-aio[mongodb]
# All backends
pip install py-key-value-aio[all]
The simplest way to get started is with the MemoryStore:
from key_value.aio.stores.memory import MemoryStore
store = MemoryStore()
Store a value with the put method:
await store.put(
key="user:123",
value={"name": "Alice", "email": "alice@example.com"},
collection="users"
)
Retrieve a value with the get method:
user = await store.get(key="user:123", collection="users")
print(user) # {"name": "Alice", "email": "alice@example.com"}
Set a TTL (time-to-live) for automatic expiration:
await store.put(
key="session:abc",
value={"user_id": "123", "expires": "2024-01-01"},
collection="sessions",
ttl=3600 # Expires in 1 hour
)
Delete a value with the delete method:
deleted = await store.delete(key="user:123", collection="users")
print(deleted) # True if the value was deleted, False otherwise
Collections allow you to organize keys into logical namespaces:
# Store users in the "users" collection
await store.put(
key="alice",
value={"name": "Alice"},
collection="users"
)
# Store sessions in the "sessions" collection
await store.put(
key="session-1",
value={"user_id": "alice"},
collection="sessions"
)
Perform batch operations for better performance:
# Put multiple values at once
await store.put_many(
keys=["user:1", "user:2", "user:3"],
values=[
{"name": "Alice"},
{"name": "Bob"},
{"name": "Charlie"}
],
collection="users"
)
# Get multiple values at once
users = await store.get_many(
keys=["user:1", "user:2", "user:3"],
collection="users"
)
# Delete multiple values at once
count = await store.delete_many(
keys=["user:1", "user:2", "user:3"],
collection="users"
)
from key_value.aio.stores.redis import RedisStore
store = RedisStore(url="redis://localhost:6379/0")
from key_value.aio.stores.dynamodb import DynamoDBStore
store = DynamoDBStore(
table_name="my-kv-store",
region_name="us-east-1"
)
from key_value.aio.stores.disk import DiskStore
store = DiskStore(directory="/path/to/storage")
Wrappers add functionality to stores. They can be stacked for combined effects:
from key_value.aio.stores.memory import MemoryStore
from key_value.aio.wrappers.logging import LoggingWrapper
from key_value.aio.wrappers.statistics import StatisticsWrapper
# Create a store with logging and statistics
store = StatisticsWrapper(
LoggingWrapper(
MemoryStore()
)
)
# Use the store normally
await store.put(key="test", value={"data": "value"})
# Access statistics
stats = store.get_statistics()
print(f"Total puts: {stats.put.count}")
See the Wrappers page for detailed documentation on all available wrappers.
Adapters provide specialized interfaces for specific use cases:
from pydantic import BaseModel
from key_value.aio.stores.memory import MemoryStore
from key_value.aio.adapters.pydantic import PydanticAdapter
class User(BaseModel):
name: str
email: str
# Create a type-safe adapter
adapter = PydanticAdapter(
key_value=MemoryStore(),
pydantic_model=User
)
# Store and retrieve type-safe models
await adapter.put(
key="user:123",
value=User(name="Alice", email="alice@example.com"),
collection="users"
)
user = await adapter.get(key="user:123", collection="users")
print(user.name) # Type-safe access: "Alice"
See the Adapters page for detailed documentation on all available adapters.
If you’re building a framework, you can use the AsyncKeyValue protocol to
allow your users to plug in any backend:
from key_value.aio.protocols.key_value import AsyncKeyValue
class YourFramework:
def __init__(self, cache: AsyncKeyValue):
self.cache = cache
async def store_session(self, session_id: str, data: dict):
await self.cache.put(
key=f"session:{session_id}",
value=data,
collection="sessions",
ttl=3600
)
async def get_session(self, session_id: str):
return await self.cache.get(
key=f"session:{session_id}",
collection="sessions"
)
Your users can then choose their own backend:
from your_framework import YourFramework
from key_value.aio.stores.memory import MemoryStore
from key_value.aio.stores.redis import RedisStore
# Development
framework = YourFramework(cache=MemoryStore())
# Production
framework = YourFramework(
cache=RedisStore(url="redis://localhost:6379/0")
)