Skip to main content

Modules/_dbmmodule.c / Modules/_gdbmmodule.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/_gdbmmodule.c

dbm.gnu wraps the gdbm library, providing a persistent dict-like object backed by a .gdbm database file. It is one of several dbm backends selected by dbm.open.

Map

LinesSymbolRole
1-80gdbm_open wrappergdbm.open(filename, flag, mode)
81-200dbmobject_subscriptdb[key] — fetch and db[key] = value — store
201-300dbmobject_keysReturn list of all keys
301-400dbmobject_deletedel db[key]
401-500dbmobject_reorganizeCompact the database file
501-600dbmobject_syncFlush in-memory cache to disk

Reading

gdbm.open

// CPython: Modules/_gdbmmodule.c:88 dbmopen
static PyObject *
dbmopen(PyObject *module, PyObject *args)
{
const char *name;
const char *flags = "r";
int iflags = GDBM_READER;
int mode = 0666;
if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
return NULL;
/* Map flag string to GDBM flag:
'r' → GDBM_READER, 'w' → GDBM_WRITER,
'c' → GDBM_WRCREAT, 'n' → GDBM_NEWDB */
...
GDBM_FILE dp = gdbm_open(name, 0, iflags, mode, NULL);
if (dp == NULL) {
PyErr_SetFromErrnoWithFilenameObject(DbmError, PyTuple_GET_ITEM(args, 0));
return NULL;
}
return newdbmobject(dp);
}

db[key] and db[key] = value

// CPython: Modules/_gdbmmodule.c:180 dbmobject_subscript
static PyObject *
dbmobject_subscript(dbmobject *dp, PyObject *key)
{
datum drec, krec;
if (!PyArg_Parse(key, "y*", &krec.dptr) ...) return NULL;
drec = gdbm_fetch(dp->di_dbm, krec);
if (drec.dptr == NULL) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
PyObject *v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
free(drec.dptr);
return v;
}

All keys and values are bytes. The datum struct holds a char * and a size_t.

keys()

// CPython: Modules/_gdbmmodule.c:280 dbm_keys
/* Iterates using gdbm_firstkey / gdbm_nextkey */
static PyObject *
dbm_keys(dbmobject *dp, PyObject *args)
{
PyObject *v = PyList_New(0);
datum key = gdbm_firstkey(dp->di_dbm);
while (key.dptr) {
PyList_Append(v, PyBytes_FromStringAndSize(key.dptr, key.dsize));
datum nextkey = gdbm_nextkey(dp->di_dbm, key);
free(key.dptr);
key = nextkey;
}
return v;
}

reorganize

// CPython: Modules/_gdbmmodule.c:440 dbm_reorganize_impl
/* gdbm never shrinks the database file; reorganize() rewrites it compactly. */
static PyObject *
dbm_reorganize_impl(dbmobject *dp)
{
if (gdbm_reorganize(dp->di_dbm) != 0) {
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
return NULL;
}
Py_RETURN_NONE;
}

gopy notes

dbm.gnu is in module/dbm/gnu/module.go. It uses cgo to call libgdbm. The gdbm.open API maps to gdbm_open(3) via C.gdbm_open. Key/value conversion uses C.GoBytes and C.CBytes. reorganize calls C.gdbm_reorganize.