Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A persistent (sqlite3) dictionary
"""
A persistent (sqlite3) python dictionary
Based on:
http://erezsh.wordpress.com/2009/05/31/filedict-bug-fixes-and-updates/
Author: Erez Shinan
Date: 31-May-2009
Copyright 2010 Matteo Bertini <matteo@naufraghi.net>
Python Software Foundation License (PSFL)
"""
import UserDict
import cPickle as pickle
import sqlite3
class SqliteDict(UserDict.DictMixin):
"A dictionary that stores its data persistently in a database"
def __init__(self, filename, flag='c', protocol=-1, writeback=False):
self.filename = filename
self.flag = flag
self.protocol = protocol
self.writeback = writeback
# flag as in http://docs.python.org/library/anydbm.html#anydbm.open
if flag in ('r', 'w'):
if not os.path.exists(filename):
raise IOError("File {0!r} missing!".format(filename))
sqlite3.register_converter("PICKLE", self._loads)
self._conn = sqlite3.connect(filename, detect_types=sqlite3.PARSE_DECLTYPES)
if flag == 'n':
self._dbdrop()
if flag in ('n', 'c'):
self._dbcreate()
def _dbdrop(self):
self._conn.execute("DROP TABLE IF EXISTS dict;")
self._conn.commit()
def _dbcreate(self):
self._conn.execute("""CREATE TABLE IF NOT EXISTS dict (idx INTEGER PRIMARY KEY,
key STRING UNIQUE,
value PICKLE);""")
self._conn.execute("CREATE INDEX IF NOT EXISTS dict_index ON dict(key);")
self._conn.commit()
def _commit(self):
if self.writeback:
self._conn.commit()
def _dumps(self, value):
return buffer(pickle.dumps(value, self.protocol))
def _loads(self, blob):
return pickle.loads(blob)
def __getitem__(self, key):
cursor = self._conn.execute("SELECT value FROM dict WHERE key=?;", (key,))
for (value,) in cursor:
return value
raise KeyError(key)
def _setitems(self, items):
parameters = ((key, self._dumps(value)) for key, value in items)
self._conn.executemany("INSERT OR REPLACE INTO dict (key, value) values (?, ?);",
parameters)
self._commit()
def __setitem__(self, key, value):
self._setitems([(key, value)])
def __delitem__(self, key):
cursor = self._conn.execute("DELETE FROM dict WHERE key=?;", (key,))
if cursor.rowcount <= 0:
raise KeyError(key)
self._commit()
def update(self, d):
self._setitems(d.iteritems())
def iterkeys(self):
return self._conn.execute("SELECT key FROM dict;")
def itervalues(self):
return self._conn.execute("SELECT value FROM dict;")
def iteritems(self):
return self._conn.execute("SELECT key, value FROM dict;")
def __iter__(self):
return self.iterkeys()
def keys(self):
return list(self.iterkeys())
def values(self):
return list(self.itervalues())
def items(self):
return list(self.iteritems())
def __contains__(self, key):
try:
self.__getitem__(key)
return True
except KeyError:
return False
def __len__(self):
return self._conn.execute("SELECT COUNT(*) FROM dict;").fetchone()[0]
def close(self):
self.sync()
self._conn.close()
def sync(self):
self._conn.commit()
def __del__(self):
self.close()
def open(filename, flag='c', protocol=-1, writeback=False):
return SqliteDict(filename, flag, protocol, writeback)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.