Complete Implementation
import csv, json
from datetime import datetime
from pathlib import Path
from collections import defaultdict
DATA_FILE = Path("expenses.json")
class ExpenseTracker:
def __init__(self):
self.expenses, self.budgets = [], {}
if DATA_FILE.exists():
data = json.loads(DATA_FILE.read_text())
self.expenses = data.get("expenses", [])
self.budgets = data.get("budgets", {})
def save(self):
DATA_FILE.write_text(json.dumps({"expenses": self.expenses, "budgets": self.budgets}, indent=2))
def add(self, amount, category, description, date=""):
self.expenses.append({
"id": len(self.expenses) + 1,
"amount": amount, "category": category,
"description": description,
"date": date or datetime.now().strftime("%Y-%m-%d"),
})
self.save()
def monthly_summary(self, year, month):
totals = defaultdict(float)
for e in self.expenses:
y, m, _ = e["date"].split("-")
if int(y) == year and int(m) == month:
totals[e["category"]] += e["amount"]
return dict(totals)
def check_budget(self, year, month):
summary = self.monthly_summary(year, month)
return [
f"OVER BUDGET {cat}: spent ${spent:.2f} / limit ${self.budgets[cat]:.2f}"
for cat, spent in summary.items()
if cat in self.budgets and spent > self.budgets[cat]
]
def export_csv(self, filepath):
with open(filepath, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["id","date","category","amount","description"])
writer.writeheader()
writer.writerows(self.expenses)
# Demo
t = ExpenseTracker()
t.add(45.50, "Food", "Grocery")
t.add(120.00, "Housing", "Electricity")
t.budgets["Food"] = 300.00
now = datetime.now()
for cat, total in t.monthly_summary(now.year, now.month).items():
print(f"{cat}: ${total:.2f}")
for alert in t.check_budget(now.year, now.month):
print(alert)
t.export_csv("expenses.csv")ποΈ Practical Exercise
Improve the expense tracker:
- Add categories to each expense and total spending per category.
- Persist expenses to a CSV or JSON file so they survive restarts.
- Add a command to show the highest single expense.
- Validate that amounts are positive numbers.
π₯ Challenge Exercise
Extend the tracker into a small personal-finance tool: store expenses with date, category, and amount in a database (SQLite), add monthly summaries and a simple budget check that warns when a category exceeds its limit, and export a report. Bonus: visualize spending by category with a Matplotlib bar chart.
π Summary
- This project builds an expense tracker that records and summarizes spending.
- Each expense holds an amount and metadata such as category and date.
- Data is persisted to a file or database so it survives restarts.
- Input validation keeps amounts sensible and positive.
- Aggregation (totals per category, monthly summaries) turns raw data into insight.
- It can grow with budgets, reports, and charts.
Interview Questions on Building an Expense Tracker
- How would you model an expense record in Python?
- How do you persist data between program runs?
- What is a good data structure for grouping expenses by category?
- How do you validate financial input safely?
- How would you generate a monthly summary report?
- Why might you use the
decimalmodule for money? - How would you add data visualization?
Related Topics
FAQ
For accurate financial calculations, prefer the decimal.Decimal type, which avoids the binary rounding errors of floats. Floats are fine for casual learning but can produce cent-level discrepancies in real money math.
Write them to storage β a CSV or JSON file for simplicity, or a SQLite database for structured queries. On startup, load the existing data back into memory before accepting new entries.
Group the expenses by their category key β a dictionary mapping category to a running total, or pandasβ groupby if you load the data into a DataFrame.
Aggregate totals per category, then plot them with Matplotlib (a bar or pie chart) or Seaborn. Keeping the data layer separate makes adding visualization straightforward.
