← Back to Blog

File Handling Mini Project — Shopping List

What you're building

The shopping list is back. Again.

Version 1 used a list. Version 2 added quantity and price with a dict.

Version 3 adds persistence. The list saves to a file when you quit. When you start the program again — it's still there.

What you need to know first

  • File handling — "r", "w" modes
  • CSV — csv.reader, csv.writer
  • Dicts — building and iterating
  • while True with break
  • input(), float(), int()

The brief

Build a program that:

  • On start: loads shopping_list.csv if it exists — picks up where you left off
  • Shows the same menu as version 2: add, remove, view, checkout, quit
  • On quit: saves the current list to shopping_list.csv
  • Next run: loads the saved list automatically

The CSV format

Each row in the file represents one item:

name,qty,price
Bread,2,1.5
Milk,1,0.9

Think before you code

  • How do you load the CSV into the dict format from version 2?
  • When do you save — only on quit, or after every change?
  • What do you do if the file doesn't exist on first run?
  • What types do qty and price need to be after loading?

Your starting point

import csv

FILENAME = "shopping_list.csv"
shopping = {}

def load(filename):
    # your code here
    pass

def save(filename, data):
    # your code here
    pass

def print_list(d):
    if not d:
        print("Your list is empty.")
    else:
        print("\nYour list:")
        for item, data in d.items():
            subtotal = data["qty"] * data["price"]
            print(f"- {item:<10} x{data['qty']}   ${subtotal:.2f}")

load(FILENAME)

while True:
    print("\n1 — Add item")
    print("2 — Remove item")
    print("3 — View list")
    print("4 — Checkout")
    print("5 — Quit")
    choice = input("Your choice: ")

    # your code here

Expected output — first run

Your choice: 1
Item name: Bread
Quantity: 2
Price per unit: $1.50
Added.

Your choice: 5
List saved. Out.

Expected output — second run

Your choice: 3

Your list:
- Bread      x2   $3.00

Your choice: 5
List saved. Out.

Heads up!

  • Load on start — use FileNotFoundError for first run
  • Save on quit — "w" mode overwrites the file with the current state
  • qty is int, price is float — convert after loading from CSV
  • Pass newline="" when writing CSV

The solution

import csv

FILENAME = "shopping_list.csv"
shopping = {}

def load(filename):
    try:
        with open(filename, "r", encoding="utf-8") as f:
            reader = csv.DictReader(f)
            for row in reader:
                shopping[row["name"]] = {
                    "qty":   int(row["qty"]),
                    "price": float(row["price"])
                }
    except FileNotFoundError:
        pass    # first run — no file yet

def save(filename, data):
    with open(filename, "w", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=["name", "qty", "price"])
        writer.writeheader()
        for name, d in data.items():
            writer.writerow({"name": name, "qty": d["qty"], "price": d["price"]})

def print_list(d):
    if not d:
        print("Your list is empty.")
    else:
        print("\nYour list:")
        for item, data in d.items():
            subtotal = data["qty"] * data["price"]
            print(f"- {item:<10} x{data['qty']}   ${subtotal:.2f}")

load(FILENAME)

while True:
    print("\n1 — Add item")
    print("2 — Remove item")
    print("3 — View list")
    print("4 — Checkout")
    print("5 — Quit")
    choice = input("Your choice: ")

    if choice == "1":
        name  = input("Item name: ").capitalize()
        qty   = int(input("Quantity: "))
        price = float(input("Price per unit: $"))
        shopping[name] = {"qty": qty, "price": price}
        print("Added.")

    elif choice == "2":
        name = input("Item to remove: ").capitalize()
        if name in shopping:
            shopping.pop(name)
            print(f"{name} removed.")
        else:
            print(f'"{name}" is not on your list.')

    elif choice == "3":
        print_list(shopping)

    elif choice == "4":
        if not shopping:
            print("Your list is empty.")
        else:
            print("\n--- Checkout ---")
            total = 0
            for item, data in shopping.items():
                subtotal = data["qty"] * data["price"]
                total += subtotal
                print(f"{item:<10} x{data['qty']}   ${subtotal:.2f}")
            print(f"Total:         ${total:.2f}")

    elif choice == "5":
        save(FILENAME, shopping)
        print("List saved. Out.")
        break

    else:
        print("Invalid choice. Enter 1 to 5.")
[ login to bookmark ] // copied! 18 views · 2 min
// resources
Exercise shopping_list_3.py
← prev File Handling Mini Project — Daily Notes next → Common File Handling Mistakes
// 0 comments
// No comments yet. Be the first.
// leave a comment

// Your comment will appear after approval.