shelve module
Overview
shelve provides a simple way to persist Python objects to disk. It behaves like a dictionary but stores its contents in a file (or set of files) that persists between program runs. Keys must be strings; values can be any object that pickle can serialize.
Under the hood, shelve uses pickle to serialize objects and dbm to store them. The shelf acts as a persistent dictionary — you read and write to it just like a regular dict, and the data survives after the program exits.
Opening a Shelf
import shelve
# Open (create if doesn't exist, read/write mode)
db = shelve.open("my_data")
# Equivalent to:
db = shelve.open("my_data", flag="c") # c = create/read/write
The flag parameter controls how the shelf is opened:
| Flag | Meaning |
|---|---|
"r" | Open existing shelf for reading only |
"w" | Open existing shelf for reading and writing |
"c" | Create if doesn’t exist; open existing for read/write (default) |
"n" | Always create a new empty shelf; fails if it exists |
# Read-only
db = shelve.open("existing_data", flag="r")
# Always start fresh
db = shelve.open("new_data", flag="n")
Reading and Writing
import shelve
db = shelve.open("config")
# Store values (any pickle-serializable object)
db["name"] = "Alice"
db["preferences"] = {"theme": "dark", "notifications": True}
db["scores"] = [95, 87, 92, 88]
# Read like a dictionary
print(db["name"]) # Alice
print(db["preferences"]) # {'theme': 'dark', 'notifications': True}
db.close()
Use the shelf as a context manager for automatic closing:
with shelve.open("config") as db:
db["last_login"] = "2026-04-21"
print(db["last_login"])
# Shelf is closed automatically
Keys Must Be Strings
Shelf keys must be strings (this is a dbm limitation, not a Python dict limitation):
with shelve.open("data") as db:
db["string_key"] = "value"
# db[123] = "value" # TypeError: keys must be strings
# Common workaround: convert int keys to strings
key = 123
db[str(key)] = "numeric key as string"
The protocol Parameter
By default, shelve uses the highest protocol available for your Python version (currently protocol 5 in Python 3.8+). You can specify a protocol explicitly:
# Use a specific protocol
db = shelve.open("data", protocol=4)
# Protocol 4: Python 3.4+, supports out-of-band buffers
# Protocol 3: Python 3.0+, not compatible with Python 2
# Protocol 2: Python 2.3+, wider compatibility
In most cases, protocol=None (the default) is what you want — it uses pickle.DEFAULT_PROTOCOL, which is the highest available.
The writeback Flag — Caching Behaviour
By default, writeback=False. The shelf only writes data when you assign to it. This is memory-efficient but means mutations to mutable objects inside the shelf aren’t saved automatically:
db = shelve.open("data")
db["list"] = [1, 2, 3]
temp = db["list"]
temp.append(4)
# db["list"] is still [1, 2, 3] — temp is a *copy*, not a reference
db["list"] = temp # Must reassign to persist
db.close()
Set writeback=True to automatically track mutations:
db = shelve.open("data", writeback=True)
db["list"] = [1, 2, 3]
db["list"].append(4) # Now this *does* persist
db.close() # Writes everything back to disk
The trade-off: writeback=True consumes more memory (it caches every accessed item) and makes close() slower (it syncs everything). Use it only when you frequently mutate nested objects.
To sync the cache without closing:
db = shelve.open("data", writeback=True)
db["counter"] = 0
for i in range(100):
db["counter"] += 1
db.sync() # Write changes to disk, keep shelf open
Closing and Syncing
Always close the shelf to ensure data is written to disk:
db = shelve.open("data")
db["key"] = "value"
db.close()
Or use the context manager:
with shelve.open("data") as db:
db["key"] = "value"
# Automatically closed
Explicitly sync to flush cached writes without closing:
db["key"] = "value"
db.sync() # Force write to disk
db["key"] = "other"
db.close() # Final close
Deleting and Checking Keys
with shelve.open("data") as db:
db["name"] = "Alice"
db["age"] = 30
# Check if key exists
print("name" in db) # True
# Delete a key
del db["age"]
# Get with default (like dict)
print(db.get("name", "default")) # Alice
print(db.get("missing", "default")) # default
Iterating Over a Shelf
with shelve.open("data") as db:
db["a"] = 1
db["b"] = 2
db["c"] = 3
# Keys
for key in db:
print(key)
# Keys and values
for key, value in db.items():
print(f"{key}: {value}")
Common Pitfalls
Shelf files are not human-readable. Unlike JSON or CSV, a shelf file is binary. Don’t try to open it in a text editor. Use a new shelve.open() call to read its contents.
Platform-specific format. The underlying dbm library produces different file formats on different operating systems. A shelf created on Linux won’t necessarily open on Windows.
Keys must be strings. This catches many people coming from regular Python dicts:
db[42] = "value" # TypeError: keys must be strings
Mutations aren’t auto-saved. As described above, modifying a mutable object retrieved from the shelf doesn’t change the stored value unless you reassign it.
See Also
- /reference/modules/pickle-module/ — the serialization module that shelve uses internally to store Python objects
- /guides/python-string-templates/ — string formatting techniques for building text output from stored data
- /guides/working-with-files/ — reading and writing files on disk, complementary to shelf persistence