There are a number of Python wrappers for LevelDB that use the
Cython
tool set to generate an interface layer to talk to the C++ classes. The most recent and often recommended is plyvel: https://plyvel.readthedocs.org/en/latest/installation.html.
However, there's also an even lower-level pure C API for LevelDB that allows you to call directly into functions in the shared library. One simple Python wrapper https://code.google.com/p/leveldb-py/ is so simple that it is implemented with a single file. That file, leveldb.py
, and the unit tests test_leveldb.py
are included in the sample code for this chapter. You don't need to use a pip
install or other command but just include the file alongside your call.
This simple wrapper, like many other scripting language wrappers, expects to have a dynamic library in a standard system location. This reflects their Unix heritage. Many installers actually rebuild LevelDB and push it into this location but this one requires you to do that work. To provide this library, go back to the build instructions in Chapter 1, Downloading LevelDB and Building with OS X, but this time, after you have built LevelDB, instead of renaming the static library, copy four files to /usr/local/lib
:
libleveldb.a libleveldb.dylib libleveldb.dylib.1 libleveldb.1.12
This ensures there is a dynamic library in the standard location so that an attempt to open a dynamic library named leveldb
will work.
The code to write a database similar to the previous Node.js code seen, looks a lot more like the C++ samples we've seen already:
#!/usr/bin/env python import leveldb # open a data store db = leveldb.DB("/tmp/testleveldb11_py.db", create_if_missing=True) # a simple Put operation db.put('name', 'William Bloggs') # a Batch operation made up of 3 Puts b = db.newBatch() db.putTo(b, key = 'spouse', val= 'Josephine Bloggs') db.putTo(b, key = 'dog', val= 'Kilroy') db.putTo(b, key = 'occupation', val= 'Dev') db.write(b, sync=True) db.close()
To read that back we can just iterate through all of the keys and get their associated value:
for k in db.keys(): print k, db.get(k)
Apart from supporting all of the basic LevelDB features we've seen so far, leveldb.py
includes prefixing logic similar to that we added in Objective-C so you can get a subset of keys. The unit tests in test_leveldb.py
include code such as:
def testPutGet(self): db = self.db_class(self.db_path, create_if_missing=True) db.put("key1", "val1") db.put("key2", "val2", sync=True) self.assertEqual(db.get("key1"), "val1") ... self.assertEqual(list(db.keys()), ["key1", "key2"]) self.assertEqual(list(db.keys(prefix="key")), ["1", "2"])
You can see from the last line that a prefixed retrieval of keys automatically strips the prefix, similar to what our code was doing to get keys for the TableView
in Objective-C.