SqliteDict
SqliteDict is a Python library that provides a persistent dictionary interface, backed by sqlite3 and using pickle for serialization. It is designed to be multithread-safe as a workaround for Python's `sqlite3` thread limitations and supports multiple tables within a single database file. It offers a simple, Pythonic dict-like interface to an SQLite database, currently at version 2.1.0, and is actively maintained.
Warnings
- breaking Version 2.0.0 and above dropped support for Python 2.x and requires Python 3.7 or newer. If you need support for older Python versions, you must use `sqlitedict` version 1.7.0 or earlier.
- gotcha By default, `autocommit` is `False` for performance reasons. Forgetting to call `db.commit()` after modifications will result in unsaved data. Always ensure you commit changes or initialize with `autocommit=True`.
- gotcha While `sqlitedict` is marketed as 'multithread-safe', this primarily refers to a workaround for Python's `sqlite3` module's threading limitations, serializing requests internally. SQLite itself operates on a single-writer model. True concurrent *writes* from multiple processes or threads will still be serialized and can lead to performance bottlenecks or locking issues if not carefully managed (e.g., with WAL mode and proper error handling).
- gotcha Improperly closing an `SqliteDict` instance (e.g., not calling `db.close()` or not using a `with` statement) can lead to data not being saved (if `autocommit` is `False`) or resource leaks. Earlier versions also had reported `AttributeError` or `TypeError` upon closing.
- gotcha By default, keys are expected to be strings. If using non-string keys (e.g., integers, tuples) or complex objects as keys, `sqlitedict` will serialize them. If deterministic serialization is critical for unordered containers or custom key types, you might need to provide custom `encode_key` and `decode_key` functions to `SqliteDict`.
Install
-
pip install sqlitedict
Imports
- SqliteDict
from sqlitedict import SqliteDict
Quickstart
from sqlitedict import SqliteDict
import os
db_path = 'my_data.sqlite'
# Clean up previous run if exists
if os.path.exists(db_path):
os.remove(db_path)
# Open a new SqliteDict with autocommit enabled (recommended for many small writes)
with SqliteDict(db_path, autocommit=True) as db:
db['user:1'] = {'name': 'Alice', 'age': 30}
db['user:2'] = {'name': 'Bob', 'age': 25}
db['settings:theme'] = 'dark'
print(f"Added 3 items. Current length: {len(db)}")
# Re-open the database (autocommit defaults to False if not specified)
with SqliteDict(db_path) as db_read_only:
print(f"Retrieved user:1: {db_read_only['user:1']}")
print(f"All keys: {list(db_read_only.keys())}")
# Manual commit is needed if autocommit is False
db_read_only['new_item'] = 'This will NOT be saved without commit()'
# db_read_only.commit() # Uncomment to save
print("Demonstrating explicit commit")
# Open without autocommit, requiring explicit commit
with SqliteDict(db_path, autocommit=False) as db_manual:
db_manual['product:101'] = {'name': 'Widget', 'price': 19.99}
db_manual.commit() # Explicitly commit changes
print(f"Added product:101. Current length: {len(db_manual)}")
# Verify the manually committed item
with SqliteDict(db_path) as db_verify:
print(f"Retrieved product:101: {db_verify['product:101']}")
# Clean up the database file
if os.path.exists(db_path):
os.remove(db_path)