Day 5 · Day 5: Files & Error Handling
Expense Tracker
Build an expense tracker that lets users add expenses with a category and amount, view a summary by category, and save/load expenses to/from a CSV file so data persists between runs.
Requirements
1. Store each expense as a dictionary with: date, category, amount, description.
2. Implement adding a new expense via user input.
3. Implement viewing all expenses in a readable table format.
4. Implement a summary showing total spending per category.
5. Save expenses to a CSV file using the csv module.
6. Load expenses from the CSV file on startup if it exists.
7. Handle file-not-found errors gracefully when loading.
2. Implement adding a new expense via user input.
3. Implement viewing all expenses in a readable table format.
4. Implement a summary showing total spending per category.
5. Save expenses to a CSV file using the csv module.
6. Load expenses from the CSV file on startup if it exists.
7. Handle file-not-found errors gracefully when loading.
import csv
import os
from datetime import date
FILENAME = "expenses.csv"
expenses = []
def add_expense(category, amount, description):
expenses.append({
"date": str(date.today()),
"category": category,
"amount": float(amount),
"description": description
})
print("Expense added.")
def view_expenses():
if not expenses:
print("No expenses recorded.")
return
print(f"{'Date':<12}{'Category':<15}{'Amount':<10}{'Description'}")
for e in expenses:
print(f"{e['date']:<12}{e['category']:<15}{e['amount']:<10.2f}{e['description']}")
def category_summary():
totals = {}
for e in expenses:
totals[e["category"]] = totals.get(e["category"], 0) + e["amount"]
print("\n--- Category Summary ---")
for cat, total in totals.items():
print(f"{cat}: ${total:.2f}")
print(f"Total spent: ${sum(totals.values()):.2f}")
def save_expenses():
with open(FILENAME, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["date", "category", "amount", "description"])
writer.writeheader()
writer.writerows(expenses)
print("Expenses saved.")
def load_expenses():
global expenses
if not os.path.exists(FILENAME):
return
with open(FILENAME, "r", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
row["amount"] = float(row["amount"])
expenses.append(row)
def main():
load_expenses()
while True:
print("\n--- Expense Tracker ---")
print("1. Add Expense")
print("2. View Expenses")
print("3. Category Summary")
print("4. Save & Exit")
choice = input("Choose an option: ")
if choice == "1":
category = input("Category: ")
amount = input("Amount: ")
description = input("Description: ")
try:
add_expense(category, float(amount), description)
except ValueError:
print("Invalid amount.")
elif choice == "2":
view_expenses()
elif choice == "3":
category_summary()
elif choice == "4":
save_expenses()
print("Goodbye!")
break
else:
print("Invalid option.")
if __name__ == "__main__":
main()
50 XP on completion
Back to Day 5
Your Code
Output
Click "Run" to execute your code...
⏳ Loading Python runtime (first run may take a few seconds)...
Log in to mark this project complete and earn XP.