Advertisement
πŸ’° Projects

Python Expense Tracker

Track income and expenses by category, view monthly summaries, set budget limits, and export reports to CSV.

⏱️ 20 min read🎯 ProjectsπŸ“… Updated 2026

Complete Implementation

Python
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")
Tip: Add a matplotlib bar chart of monthly spending per category β€” turns this into a data visualization project too.

πŸ‹οΈ Practical Exercise

Improve the expense tracker:

  1. Add categories to each expense and total spending per category.
  2. Persist expenses to a CSV or JSON file so they survive restarts.
  3. Add a command to show the highest single expense.
  4. 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 decimal module for money?
  • How would you add data visualization?

FAQ

Should I store money as a float? +

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.

How do I make expenses persist between runs? +

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.

How do I total spending by category? +

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.

How can I visualize the spending? +

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.