Python

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.

August 2026 5 min read 12 views 0 hearts

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.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.