The fastest way to learn Python is not to watch more tutorials. It is to build something. Today you are building a real Python project from scratch — simple enough to finish in one sitting, complex enough to teach you skills you will use in every project after this.
Setup
Make sure you have Python 3.12 or later installed. Create a folder called expense-tracker. Create a file called expenses.csv with sample data:
1date,description,amount,category
22026-01-01,Coffee,4.50,Food
32026-01-02,Netflix,15.99,Entertainment
42026-01-03,Groceries,67.30,Food
52026-01-04,Gym,29.99,Health
62026-01-05,Amazon,43.20,Shopping
72026-01-06,Electricity,85.00,Bills
82026-01-07,Restaurant,38.50,FoodStep 1: Read the Data
1import csv
2from collections import defaultdict
3
4def read_expenses(filename):
5 expenses = []
6 with open(filename, 'r') as file:
7 reader = csv.DictReader(file)
8 for row in reader:
9 expenses.append({
10 'date': row['date'],
11 'description': row['description'],
12 'amount': float(row['amount']),
13 'category': row['category']
14 })
15 return expenses
16
17expenses = read_expenses('expenses.csv')
18print(f"Loaded {len(expenses)} expenses")csv.DictReader reads the CSV and treats the first row as column headers. float(row["amount"]) converts text "4.50" into the number 4.50 so we can do maths with it. We build a list of dictionaries — one dictionary per expense row.
Step 2: Analyse by Category
1def analyse_by_category(expenses):
2 categories = defaultdict(float)
3 for expense in expenses:
4 categories[expense['category']] += expense['amount']
5 return dict(categories)
6
7def display_summary(expenses):
8 total = sum(e['amount'] for e in expenses)
9 categories = analyse_by_category(expenses)
10
11 print("\n" + "=" * 40)
12 print("EXPENSE SUMMARY")
13 print("=" * 40)
14 print(f"Total spent: ${total:.2f}")
15 print("\nBy category:")
16
17 sorted_categories = sorted(
18 categories.items(),
19 key=lambda x: x[1],
20 reverse=True
21 )
22 for category, amount in sorted_categories:
23 percentage = (amount / total) * 100
24 print(f" {category}: ${amount:.2f} ({percentage:.1f}%)")defaultdict(float) creates a dictionary that automatically starts new keys at 0.0. sorted() with key=lambda x: x[1] sorts by the second element of each tuple. :.2f in f-strings formats numbers to exactly 2 decimal places.
Step 3: Budget Checker
1BUDGETS = {
2 'Food': 150.00,
3 'Entertainment': 50.00,
4 'Health': 100.00,
5 'Shopping': 100.00,
6 'Bills': 200.00
7}
8
9def check_budgets(expenses):
10 categories = analyse_by_category(expenses)
11 print("\nBudget status:")
12 for category, budget in BUDGETS.items():
13 spent = categories.get(category, 0)
14 remaining = budget - spent
15 status = "OK" if remaining >= 0 else "OVER BUDGET"
16 print(f" {category}: ${spent:.2f} / ${budget:.2f} — {status}")
17 if remaining < 0:
18 print(f" ⚠ Over by ${abs(remaining):.2f}")What You Actually Learned
File I/O, CSV parsing, dictionaries, functions, list sorting, lambda functions, f-strings, default arguments, defaultdict, and constants. Every one of these concepts appears constantly in real Python projects.
Do not move to the next tutorial yet. Instead, modify this project. Add a new expense category, calculate the average daily spend, filter expenses by date range, or add colour to the terminal output.

