// Data Structures
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 Truewithbreakinput(),float(),int()
The brief
Build a program that:
- On start: loads
shopping_list.csvif 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
FileNotFoundErrorfor first run - Save on quit —
"w"mode overwrites the file with the current state - qty is
int, price isfloat— 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.")
// resources
// 0 comments
// No comments yet. Be the first.
// leave a comment