Why Your Python Programs Should Remember Things Without a Database
Learn how Python's shelve module lets you persist data between program runs without setting up a database, perfect for caching, tracking user progress, and saving custom objects effortlessly.
I remember the exact moment I realized databases weren't always the answer. I was building a small web scraper for PythonSkillset.com that needed to remember which articles it had already processed. Setting up SQLite felt like using a sledgehammer to crack a nut. Then I discovered shelve, and suddenly, persistence became almost effortless.
What is Shelve, Anyway?
Think of shelve as Python's built-in way to save objects to disk without thinking about formats, schemas, or SQL queries. It's like having a dictionary that lives on your hard drive. You put things in, you take things out, and Python handles all the complexity behind the scenes.
When you use a regular dictionary in Python, everything disappears when your program ends. Shelve keeps that data around. When you run your script tomorrow, yesterday's dictionary is still there, full of everything you saved.
Getting Started with Shelve
Here's the simplest example I can show you:
import shelve
# Open a shelf file (it creates one if it doesn't exist)
with shelve.open('pythonskillset_data') as shelf:
shelf['site_name'] = 'PythonSkillset.com'
shelf['articles_published'] = 42
shelf['tags'] = ['python', 'tutorials', 'guides']
When this code finishes, that data is on your disk. Run it again with different values, and you'll see how it accumulates.
The Magic Part: Any Python Object Works
This is where shelve really shines compared to simple text files or JSON. You can store custom objects, lists of objects, dictionaries within dictionaries - anything that's pickleable (which covers almost everything you'll use).
class Article:
def __init__(self, title, author, word_count):
self.title = title
self.author = author
self.word_count = word_count
self.completed = False
# Save your custom objects
with shelve.open('articles_db') as db:
db['tutorial_001'] = Article("Python Lists Explained", "PythonSkillset Staff", 1200)
db['tutorial_002'] = Article("Understanding Dictionaries", "PythonSkillset Staff", 950)
Next time your program runs, those Article objects come back exactly as they were, with all their methods and attributes intact.
When Shelve Saves the Day
I use shelve most often for caching. When PythonSkillset.com's article generator creates content, the first run might take 30 seconds to fetch data and process everything. With shelve, I can store intermediate results:
import shelve
import time
def generate_article_titles(category):
# Simulating a slow operation
time.sleep(2)
return ['title_1', 'title_2', 'title_3']
with shelve.open('cache') as cache:
if 'titles' in cache:
titles = cache['titles']
else:
titles = generate_article_titles('python')
cache['titles'] = titles
That second run? Instant. No waiting. No reprocessing.
Where You Should Be Careful
Shelve isn't perfect for everything. Here's what I've learned the hard way:
- Multiple programs writing at once? That's a recipe for corruption. Shelve isn't designed for concurrent access. If you need that, look at databases.
- Very large datasets will slow down. Shelve loads everything into memory when you access it. For big data, SQLite handles things better.
- Keys must be strings. You can't use integers or tuples as keys like you can with regular dictionaries.
A Real-World Example from PythonSkillset
At PythonSkillset.com, we use shelve to track which tutorials readers have completed. When someone finishes "Python Basics Part 1", we update their progress:
def track_progress(user_id, tutorial_name):
with shelve.open('user_progress') as progress:
if user_id not in progress:
progress[user_id] = []
completed = progress[user_id]
if tutorial_name not in completed:
completed.append(tutorial_name)
progress[user_id] = completed
This keeps state between sessions without needing a full database server. It's simple, it works, and it's been running for months without issues.
The Bottom Line
Shelve bridges the gap between throwaway scripts and full database solutions. When your program needs to remember something between runs, but you don't want to write SQL or handle file formats, reach for shelve. It's been part of Python's standard library for decades for good reason - sometimes the simplest solution is the one that gets the job done with the least fuss.
Next time you're about to reach for a database when a dictionary would do, remember that shelve can make that dictionary live just as long as you need it to.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.