High-performance Python bindings for RistrettoDB, the tiny, blazingly fast, embeddable SQL engine.
- Original SQL API: 2.8x faster than SQLite for general SQL operations
- Table V2 Ultra-Fast API: 4.57x faster than SQLite for append-only workloads
- Zero Dependencies: Pure Python using ctypes (no additional packages required)
- Context Managers: Automatic resource cleanup with
withstatements - Type Safety: Full type hints for better IDE support
- Error Handling: Comprehensive exception handling with detailed error messages
| API | Use Case | Performance vs SQLite |
|---|---|---|
| Original SQL | General SQL operations | 2.8x faster |
| Table V2 | High-speed logging, IoT data | 4.57x faster |
# From the RistrettoDB root directory
cd ../../
make libpython3 example.pyfrom ristretto import RistrettoDB, RistrettoTable, RistrettoValue
# Original SQL API - General Purpose
with RistrettoDB("myapp.db") as db:
db.exec("CREATE TABLE users (id INTEGER, name TEXT, score REAL)")
db.exec("INSERT INTO users VALUES (1, 'Alice', 95.5)")
results = db.query("SELECT * FROM users WHERE score > 90")
for row in results:
print(f"User: {row['name']}, Score: {row['score']}")
# Table V2 API - Ultra-Fast Writes
with RistrettoTable.create("events",
"CREATE TABLE events (timestamp INTEGER, event TEXT(32))") as table:
values = [
RistrettoValue.integer(1672531200),
RistrettoValue.text("user_login")
]
table.append_row(values)
print(f"Total events: {table.get_row_count()}")db = RistrettoDB(filename: str)exec(sql: str)- Execute DDL/DML statementsquery(sql: str, callback=None) -> List[dict]- Execute SELECT queriesclose()- Close database connectionversion() -> str- Get library version (static method)
with RistrettoDB("mydb.db") as db:
db.exec("CREATE TABLE test (id INTEGER)")
# Automatically closed when exiting with blocktable = RistrettoTable.create(name: str, schema_sql: str)
table = RistrettoTable.open(name: str)append_row(values: List[RistrettoValue]) -> bool- High-speed row insertionget_row_count() -> int- Get total number of rowsclose()- Close table
with RistrettoTable.create("logs", "CREATE TABLE logs (timestamp INTEGER)") as table:
table.append_row([RistrettoValue.integer(1672531200)])
# Automatically closed when exiting with blockRistrettoValue.integer(value: int) # Create integer value
RistrettoValue.real(value: float) # Create real/float value
RistrettoValue.text(value: str) # Create text value
RistrettoValue.null() # Create null valuetype: RistrettoColumnType- Column type (INTEGER, REAL, TEXT, NULLABLE)value: Any- The actual valueis_null: bool- Whether value is null
from ristretto import RistrettoError, RistrettoResult
try:
with RistrettoDB("mydb.db") as db:
db.exec("INVALID SQL")
except RistrettoError as e:
print(f"Database error: {e}")
print(f"Error code: {e.result_code}")# IoT sensor data collection
with RistrettoTable.create("sensors",
"CREATE TABLE sensors (timestamp INTEGER, temp REAL, device_id INTEGER)") as table:
for reading in sensor_stream():
values = [
RistrettoValue.integer(reading.timestamp),
RistrettoValue.real(reading.temperature),
RistrettoValue.integer(reading.device_id)
]
table.append_row(values)# Web analytics event ingestion
with RistrettoTable.create("events",
"CREATE TABLE events (timestamp INTEGER, user_id INTEGER, action TEXT(32))") as events:
for event in event_stream():
events.append_row([
RistrettoValue.integer(event.timestamp),
RistrettoValue.integer(event.user_id),
RistrettoValue.text(event.action)
])# Tamper-evident security logging
with RistrettoDB("audit.db") as db:
db.exec("CREATE TABLE audit_log (timestamp INTEGER, user TEXT, action TEXT)")
for audit_event in security_events():
db.exec(f"INSERT INTO audit_log VALUES ({audit_event.timestamp}, "
f"'{audit_event.user}', '{audit_event.action}')")- Use Table V2 for Write-Heavy Workloads: 4.57x faster than SQLite
- Batch Operations: Group multiple inserts when possible
- Context Managers: Always use
withstatements for automatic cleanup - Text Value Cleanup: Text values are automatically managed
- Memory Mapping: RistrettoDB uses memory-mapped I/O for zero-copy performance
- Python 3.6+
- RistrettoDB library built (
make lib) - POSIX-compliant system (Linux, macOS, BSD)
-
Build RistrettoDB:
cd ../../ && make lib
-
Copy Python bindings:
cp examples/python/ristretto.py your_project/
-
Import and use:
from ristretto import RistrettoDB
The Python bindings use ctypes to interface with the RistrettoDB C library:
Python Application
↓
Python Bindings (ristretto.py)
↓ ctypes
RistrettoDB C Library (libristretto.so)
↓
Memory-Mapped Files
RistrettoDB is currently single-threaded. For multi-threaded applications:
- Use separate database instances per thread
- Implement application-level locking if sharing databases
- Consider using separate files for different threads
RuntimeError: Could not find libristretto.so
Solution: Build the library first:
cd ../../ && make libOSError: [Errno 13] Permission denied
Solution: Check file permissions or run with appropriate privileges
RistrettoError: PARSE_ERROR
Solution: Check SQL syntax - RistrettoDB supports a subset of SQL
Found a bug or want to improve the Python bindings? Please open an issue or submit a pull request at the main RistrettoDB repository.
MIT License - same as RistrettoDB core library.