Plyvel, a fast and feature-rich Python interface to LevelDB
Plyvel is a fast and feature-rich Python interface to LevelDB. It provides a comprehensive, high-performance Pythonic API that wraps most of the underlying LevelDB C++ API, leveraging Cython for speed. Key features include support for write batches, database snapshots, flexible iterators, and prefixed databases. The library is actively maintained, with version 1.5.1 released in January 2024, consistently adding support for new Python versions and ensuring compatibility with recent LevelDB releases.
Warnings
- breaking Plyvel 1.3.0 (released October 2020) completely dropped support for Python 2. Users migrating to newer Plyvel versions must ensure their projects are running on Python 3.
- gotcha Installing Plyvel from source (not via pre-built wheels) requires LevelDB development headers and a compatible LevelDB shared library (>= 1.21 for Plyvel 1.4.0+). Failing to provide these can lead to compilation errors or `ImportError` due to undefined symbols. On Linux, `pip install plyvel` often works due to embedded LevelDB in wheels, but if building from source, install `libleveldb-dev` (or equivalent) first.
- gotcha Closing a `plyvel.DB` instance while it is actively being accessed by other threads can lead to hard crashes due to a lack of internal synchronization. Ensure that no other threads are performing database operations concurrently when calling `DB.close()`.
- gotcha Implementing custom LevelDB comparators using Python callables in Plyvel incurs a significant performance penalty (e.g., up to a 4x slowdown for bulk writes) compared to LevelDB's native C++ comparators.
Install
-
pip install plyvel -
sudo apt-get install libleveldb1v5 libleveldb-dev python3-dev pip install plyvel
Imports
- plyvel
import plyvel
- DB
db = plyvel.DB(...)
Quickstart
import plyvel
import os
import shutil
# Define a path for the LevelDB database
db_path = '/tmp/testdb_plyvel_quickstart'
# Clean up any previous database at the path
if os.path.exists(db_path):
shutil.rmtree(db_path)
try:
# Open a new database, creating it if it doesn't exist
# Using a context manager ensures the database is properly closed
with plyvel.DB(db_path, create_if_missing=True) as db:
print(f"Database opened at: {db_path}")
# Put key-value pairs (keys and values must be bytes)
db.put(b'name', b'Alice')
db.put(b'age', b'30')
db.put(b'city', b'New York')
# Get a value
name = db.get(b'name')
if name:
print(f"Name: {name.decode('utf-8')}")
# Iterate over all key-value pairs
print("\nAll entries:")
for key, value in db:
print(f" {key.decode('utf-8')}: {value.decode('utf-8')}")
# Delete a key
db.delete(b'age')
print("\nAfter deleting 'age':")
# Verify deletion by iterating again
for key, value in db:
print(f" {key.decode('utf-8')}: {value.decode('utf-8')}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Ensure cleanup even if an error occurs
if os.path.exists(db_path):
shutil.rmtree(db_path)
print(f"\nCleaned up database directory: {db_path}")