Discover 7 Lightweight Python Databases for Small Projects
This article introduces seven lesser‑known Python databases—PickleDB, TinyDB, ZODB, Durus, Buzhug, Gadfly, and PyTables—detailing their main features, typical use cases, cautions, and providing basic code examples to help developers quickly evaluate and adopt them.
Python, as a high‑level programming language, is used to implement many types of databases, including relational, NoSQL, embedded, and object‑oriented databases. The following lesser‑known databases can help you deepen your understanding by studying their source code.
PickleDB
PickleDB is a lightweight key‑value store written in Python that uses JSON files for persistence. It provides a simple, dictionary‑like API suitable for small projects or quick persistence.
Key Features
Very lightweight; not suited for large datasets or high‑concurrency scenarios.
Simple API similar to Python dict for easy learning and use.
JSON‑based storage enables easy reading, modification, and data exchange.
Data is persisted to a JSON file, ensuring durability across restarts.
No external dependencies; runs with just a Python environment.
Use Cases
Configuration storage for applications that rarely change.
Small projects requiring rapid development without complex database setup.
Learning and teaching basic database operations.
Temporary data storage during development or testing.
Notes
Performance and scalability are limited; unsuitable for large‑scale or high‑concurrency workloads.
JSON file storage lacks encryption and access control, making it inappropriate for sensitive data.
Basic Usage
import pickledb
# Create or open a database
db = pickledb.load('example.db', auto_dump=True)
# Insert data
db.set('key1', 'value1')
# Retrieve data
value = db.get('key1')
print(value) # Output: value1
# Check if a key exists
exists = db.exists('key1')
print(exists) # Output: True
# Delete data
db.rem('key1')
# Get all keys
keys = db.getall()
print(keys)
# Save changes
db.dump()TinyDB
TinyDB is a lightweight, document‑oriented NoSQL database written in Python. It stores data in JSON files and requires no external dependencies, making it ideal for small projects and embedded applications.
Key Features
Pure Python, no server or external dependencies required.
Document‑oriented storage; each document is a dictionary that can contain nested structures.
Simple, dict‑like API for easy CRUD operations.
Powerful query language supporting complex conditions, logical combinations, and regular expressions.
Extensible via plugins for custom storage engines and middleware.
Basic transaction support for atomic operations.
Use Cases
Small projects where quick development and minimal setup are priorities.
Embedded applications that need an on‑disk, dependency‑free store.
Prototyping phases where data persistence is needed before migrating to a full‑featured database.
Configuration storage for applications requiring structured, persistent settings.
Notes
Performance and scalability are limited; not ideal for large datasets or high‑concurrency workloads.
File‑based storage can degrade as the JSON file grows.
Basic Usage
from tinydb import TinyDB, Query
# Create or open a database
db = TinyDB('db.json')
# Insert data
db.insert({'name': 'John', 'age': 22})
db.insert({'name': 'Jane', 'age': 25})
# Query data
User = Query()
result = db.search(User.name == 'John')
print(result) # Output: [{'name': 'John', 'age': 22}]
# Update data
db.update({'age': 23}, User.name == 'John')
# Delete data
db.remove(User.name == 'Jane')
# Retrieve all data
all_data = db.all()
print(all_data)
# Close the database
db.close()ZODB
ZODB (Zope Object Database) is an object‑oriented database system for persisting Python objects directly, without converting them to relational tables. It is well suited for applications that need to store complex data structures.
Key Features
Object‑oriented storage eliminates the need for ORM mapping.
Transparent persistence; serialization is handled automatically.
ACID transaction support ensures data integrity.
Versioning and history tracking allow rollbacks.
Extensible storage back‑ends (file, memory, network).
Schema‑free design offers flexibility.
Use Cases
Persisting complex objects in content management systems or scientific applications.
Python‑centric applications that benefit from direct object storage.
Any scenario requiring reliable transaction support.
Notes
Performance and scalability are suitable for medium‑size workloads; large‑scale high‑performance needs may require optimization or another database.
Learning curve for developers accustomed to relational databases.
Community and ecosystem are relatively small.
Basic Usage
import transaction
from ZODB import FileStorage, DB
import persistent
# Define a persistent object class
class Person(persistent.Persistent):
def __init__(self, name, age):
self.name = name
self.age = age
# Create a file storage and database
storage = FileStorage.FileStorage('mydata.fs')
db = DB(storage)
# Open a connection
connection = db.open()
root = connection.root()
# Add an object
root['person'] = Person('John Doe', 30)
# Commit transaction
transaction.commit()
# Retrieve the object
person = root['person']
print(person.name, person.age)
# Close connection and storage
connection.close()
db.close()
storage.close()Durus
Durus is a lightweight, object‑oriented persistence system written in Python. It offers simple transaction support and stores objects directly on disk, making it suitable for small projects that do not require complex queries.
Key Features
Object‑oriented storage of Python objects.
Persistence to disk ensures data survives restarts.
Basic transaction support for atomic operations.
Simple, easy‑to‑learn API.
Very lightweight with no external dependencies.
Use Cases
Small projects needing straightforward data persistence.
Python applications that want tight integration with native objects.
Rapid prototyping where a full‑featured database is unnecessary.
Notes
Limited performance and scalability; not ideal for large datasets.
Lacks advanced query and indexing capabilities.
Community support is modest.
Basic Usage
from durus.persistent import Persistent
from durus.connection import Connection
from durus.storage import FileStorage
# Define a persistent object class
class Person(Persistent):
def __init__(self, name, age):
self.name = name
self.age = age
# Create storage and connection
storage = FileStorage('mydata.durus')
connection = Connection(storage)
root = connection.get_root()
# Add an object
root['person'] = Person('John Doe', 30)
# Commit transaction
connection.commit()
# Retrieve the object
person = root['person']
print(person.name, person.age)
# Close connection and storage
connection.close()
storage.close()Buzhug
Buzhug is a pure‑Python lightweight database that provides a simple SQL‑like query language. It is designed for small projects and teaching purposes where a full relational engine would be overkill.
Key Features
Implemented entirely in Python; no external dependencies.
SQL‑like query syntax for familiar data manipulation.
Lightweight and easy to install.
Intuitive API suitable for beginners.
Schema‑free, allowing flexible field addition.
Use Cases
Small applications that need simple data storage.
Educational settings for learning basic database concepts and SQL.
Rapid prototyping before moving to a more robust system.
Notes
Performance and functionality are limited; best for small datasets.
Community and ecosystem are small, so issues may need self‑resolution.
Does not support advanced transactions or indexing.
Basic Usage
from buzhug import Base
# Create or open a database
db = Base('people').create(('name', str), ('age', int))
# Insert data
db.insert(name='John Doe', age=30)
db.insert(name='Jane Doe', age=25)
# Query data
for person in db.select():
print(person.name, person.age)
# Update data
db.update(db.name == 'John Doe', age=31)
# Delete data
db.delete(db.name == 'Jane Doe')
# Close the database
db.close()Gadfly
Gadfly is a pure‑Python lightweight relational database that implements a subset of SQL. It runs without a server and is useful for teaching, learning, and small‑scale applications.
Key Features
Fully written in Python; runs anywhere Python is available.
Supports standard SQL queries.
Lightweight and suitable for embedded use.
No server or complex configuration required.
Use Cases
Learning SQL and basic database concepts.
Small projects needing simple relational storage.
Rapid development and prototyping.
Notes
Performance and scalability are limited due to pure‑Python implementation.
Community activity is low; some issues may require custom solutions.
Compatibility with modern Python versions may need adjustments.
Basic Usage
from gadfly import gadfly
# Create or connect to a database
connection = gadfly('mydb', 'mydb_directory')
cursor = connection.cursor()
# Create a table
cursor.execute("CREATE TABLE people (name VARCHAR, age INTEGER)")
# Insert data
cursor.execute("INSERT INTO people (name, age) VALUES ('John Doe', 30)")
cursor.execute("INSERT INTO people (name, age) VALUES ('Jane Doe', 25)")
# Query data
cursor.execute("SELECT * FROM people")
for row in cursor.fetchall():
print(row)
# Update data
cursor.execute("UPDATE people SET age = 31 WHERE name = 'John Doe'")
# Delete data
cursor.execute("DELETE FROM people WHERE name = 'Jane Doe'")
# Commit and close
connection.commit()
connection.close()PyTables
PyTables is an open‑source library for managing large scientific datasets, built on the HDF5 file format. It provides efficient storage, compression, hierarchical organization, and powerful querying, making it ideal for data‑intensive scientific computing.
Key Features
Uses HDF5 as the underlying storage format.
Supports multiple compression algorithms for space efficiency.
Hierarchical organization similar to a file system.
Handles datasets that exceed available memory.
Broad data‑type support, including numeric, string, and object arrays.
Powerful query capabilities for selective data retrieval.
Seamless integration with NumPy arrays.
Installation
Install via pip: pip install tables Basic Usage
import numpy as np
import tables
# Create an HDF5 file
with tables.open_file('example.h5', mode='w') as file:
# Create a group
group = file.create_group('/', 'data_group', 'Data Group')
# Create a structured array
data = np.array([(1, 'Hello'), (2, 'World')],
dtype=[('number', 'i4'), ('word', 'S10')])
# Create a table
table = file.create_table(group, 'example_table', description=data.dtype, title='Example Table')
# Insert data
row = table.row
for item in data:
row['number'] = item['number']
row['word'] = item['word']
row.append()
table.flush()
# Query data
for row in table.where('number > 1'):
print(row['number'], row['word'].decode('utf-8'))
# Read all data into a NumPy array
np_data = table.read()
print(np_data)Use Cases
Scientific computing and data analysis (e.g., climate data, genomics, physics simulations).
Managing datasets larger than available RAM.
Data archiving and sharing using the widely supported HDF5 format.
Notes
Performance may depend on data layout and compression choices; tuning may be required.
Requires the HDF5 library; proper installation is necessary.
Cross‑platform compatibility is good, but version mismatches can affect portability.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
