-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sqlite3 as another possible backing store for the dbm module #100414
Comments
See also #48033 |
IIRC, I've got a fairly up-to-date branch for this, based on your previous efforts, Raymond. |
@rhettinger, would you like to continue the discussion here or on #48033? There is no use in keeping two identical issues open; let's close one of them. |
Here are my 50 cents about this. TL;DR
In details
The biggest problem with import dbm.dumb
import shelve
import itertools
database = dbm.dumb.open("test", "c")
shelf = shelve.Shelf(database)
if "key" in shelf:
print("The stored value is: " + shelf["key"])
input("Press ENTER to continue")
del shelf["key"]
try:
for index in itertools.count():
print(f"Persist value {index} to database")
shelf["key"] = f"value {index} " + ("x" * index)
except:
print("Exiting gracefully. Try killing the Python process.") Performance measurementsSorry. in Windows I do not have dbm.gnu. write
batch
read
combined
|
If you want to run with this, do whatever makes sense for you. The other issue is mostly stale and likely needs a fresh start. A new first draft is likely just an afternoon project. If you don't want to run with it, let me know and I'll work on it. I don't know that there needs to be much discussion because we have If you're interested, here's some code that can be used as a starting point: import sqlite3
from contextlib import suppress
from collections.abc import MutableMapping
BUILD_TABLE = "CREATE TABLE Dict (key TEXT NOT NULL, value BLOB NOT NULL, PRIMARY KEY (key));"
GET_SIZE = "SELECT COUNT (*) FROM Dict;"
LOOKUP_KEY = "SELECT value FROM Dict WHERE key = ?;"
STORE_KV = "REPLACE INTO Dict (key, value) VALUES (?, ?);"
DELETE_KEY = "DELETE FROM Dict WHERE key = ?;"
ITER_KEYS = "SELECT key FROM Dict;"
class SQLiteDict(MutableMapping):
def __init__(self, dbname=':memory:'):
self.conn = sqlite3.connect(dbname, isolation_level=None)
self.conn.execute('PRAGMA journal_mode = wal')
with suppress(sqlite3.OperationalError):
self.conn.execute(BUILD_TABLE)
def __len__(self):
return self.conn.execute(GET_SIZE).fetchone()[0]
def __getitem__(self, key):
value_tuple = self.conn.execute(LOOKUP_KEY, (key,)).fetchone()
if value_tuple is None:
raise KeyError(key)
return value_tuple[0]
def __setitem__(self, key, value):
self.conn.execute(STORE_KV, (key, value));
self.conn.commit()
def __delitem__(self, key):
if key not in self:
raise KeyError(key)
self.conn.execute(DELETE_KEY, (key,));
self.conn.commit()
def __iter__(self):
curs = self.conn.execute(ITER_KEYS)
while (value_tuple := curs.fetchone()):
yield value_tuple[0]
curs.close()
def close(self):
self.conn.close()
self.conn = None
def __enter__(self):
return self
def __exit__(self, *args):
self.close() Other thoughts:
|
I prefer closing the old issue; we definitely need a fresh start here. I'll take care of it.
I'll give it a shot; it'll be a nice chance for me to get to know the shelve and dbm modules better.
Thanks! |
Finally got back to this; I added @rhettinger's patch, amended it so the generic |
This comment was marked as resolved.
This comment was marked as resolved.
Co-authored-by: Raymond Hettinger <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]> Co-authored-by: Mariusz Felisiak <[email protected]>
Co-authored-by: Alex Waygood <[email protected]>
Co-authored-by: Raymond Hettinger <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]> Co-authored-by: Mariusz Felisiak <[email protected]>
…hon#115449) Co-authored-by: Alex Waygood <[email protected]>
This seems to have broken the beaker library: bbangert/beaker#242 . Its test suite, which passes fine on Python 3.12, fails on Python 3.13 in dbm-based tests, with errors about sqlite3 thread violations. Isn't it a bit bad if code using dbm which worked fine with the previous default backend fails with the new one? |
of course, I guess it's possible beaker is just not handling threads correctly, but the other backends weren't smart enough to notice, and beaker's tests aren't good enough to catch it either. I'm not sure which is the case. |
Right now we support
ndbm
andgnu.dbm
which might or might not be part of a given build. The fallback is the super slowdumbdbm
. Not the sqlite3 is part of the standard build, we can do better.The module docstring says:
The future is now. Let's provide a fast, stable, robust, always available alternative.
This can be done will pure python calls to the existing
sqlite3
module, or there can be a C extension that calls the Sqlite3 C API directly.This would automatically be available to the
shelve
module, giving us a high quality, persistent key-value store.Linked PRs
The text was updated successfully, but these errors were encountered: