Table of Contents
Choosing Your Small Project
In this chapter you’ll build one small project that uses what you’ve learned so far. You can choose:
- A tiny web project (using Flask)
- A tiny data project (using pandas / matplotlib)
You do not need to build both. Pick one that sounds more fun or useful to you.
We’ll walk through:
- A simple web project idea and how to build it.
- A simple data project idea and how to build it.
- How to extend your chosen project.
You can treat this chapter as a “recipe”: follow it once as written, then modify it.
Option 1: Tiny Web Project – Personal Notes Web App
Project idea
Build a very simple “personal notes” web app where you can:
- Open a page in your browser.
- Type a short note into a form.
- See all saved notes listed on the page.
We’ll keep everything in memory (a Python list), so when you stop the program, the notes disappear. This keeps the code short and focused.
You should already have seen in the web chapters:
- How to install and run Flask.
- What routes and templates are.
Here we just put those pieces together into a complete mini-project.
Project structure
Create a folder for your project, for example:
notes_app/app.pytemplates/index.html
You run app.py, then open the app in your browser.
Step 1: Basic Flask app and home page
In app.py:
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
# This list will store our notes while the app is running
notes = []
@app.route("/", methods=["GET"])
def index():
return render_template("index.html", notes=notes)
if __name__ == "__main__":
app.run(debug=True)
Create the templates folder, and inside it create index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Notes</title>
</head>
<body>
<h1>My Notes</h1>
<!-- Form to add a new note -->
<form method="post" action="{{ url_for('add_note') }}">
<input type="text" name="note_text" placeholder="Write a note..." required>
<button type="submit">Add</button>
</form>
<h2>Saved notes:</h2>
<ul>
{% for note in notes %}
<li>{{ note }}</li>
{% else %}
<li>No notes yet.</li>
{% endfor %}
</ul>
</body>
</html>
If you run app.py now, it will fail because we haven’t defined the add_note route yet. That’s the next step.
Step 2: Handling the form (adding notes)
Add a new route in app.py before the if __name__ == "__main__": line:
@app.route("/add", methods=["POST"])
def add_note():
note_text = request.form.get("note_text", "").strip()
if note_text:
notes.append(note_text)
# Redirect back to the home page so the user sees the updated list
return redirect(url_for("index"))
Now update the form in index.html to match the /add route if needed (we already used url_for('add_note'), so it should be fine).
Your full app.py now:
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
notes = [] # in-memory storage
@app.route("/", methods=["GET"])
def index():
return render_template("index.html", notes=notes)
@app.route("/add", methods=["POST"])
def add_note():
note_text = request.form.get("note_text", "").strip()
if note_text:
notes.append(note_text)
return redirect(url_for("index"))
if __name__ == "__main__":
app.run(debug=True)
Run python app.py, open the URL shown in the terminal (usually http://127.0.0.1:5000/), and:
- Type a note.
- Click “Add”.
- See it appear in the list.
Step 3: Adding a “delete note” feature
Let’s allow deleting individual notes by index. We’ll:
- Display a delete button next to each note.
- Send its index to a
/delete/<index>route.
In app.py add:
@app.route("/delete/<int:index>", methods=["POST"])
def delete_note(index):
if 0 <= index < len(notes):
notes.pop(index)
return redirect(url_for("index"))
Update index.html to include a delete form for each note:
<ul>
{% for note in notes %}
<li>
{{ loop.index0 }}. {{ note }}
<form method="post" action="{{ url_for('delete_note', index=loop.index0) }}"
style="display:inline">
<button type="submit">Delete</button>
</form>
</li>
{% else %}
<li>No notes yet.</li>
{% endfor %}
</ul>Now you have:
- A web form to add notes.
- A list that updates.
- A way to delete notes.
This is a complete small web project.
Ideas to extend the web project
Pick 1–2 small improvements:
- Add timestamps to notes using
datetime. - Limit note length, and show a message if it’s too long.
- Add a second page, e.g.
/about, explaining what the app is. - Save notes to a file (use the file chapter) so they persist between runs.
- Style the page with basic CSS.
Option 2: Tiny Data Project – Simple CSV Data Explorer
Project idea
Build a small script that:
- Loads data from a CSV file using
pandas. - Shows basic statistics (count, mean, min, max).
- Creates a simple plot using
matplotlib. - Interacts with the user via the terminal (user chooses what to see).
You already saw the basics of pandas and matplotlib; here we combine them into a single usable script.
We’ll assume:
- You can install packages with
pip. - You have a CSV file or can download one.
Setup
Install needed libraries (if not already installed):
pip install pandas matplotlibPick a CSV file, for example:
- A small dataset you downloaded (e.g. from Kaggle).
- Or create your own
data.csvlike:
name,age,score
Alice,23,88
Bob,30,92
Charlie,25,79
Diana,28,95
Place data.csv in the same folder as your script.
Step 1: Load and briefly inspect the data
Create data_explorer.py:
import pandas as pd
FILE_NAME = "data.csv"
def load_data():
try:
df = pd.read_csv(FILE_NAME)
print(f"Loaded {len(df)} rows from {FILE_NAME}")
return df
except FileNotFoundError:
print(f"ERROR: Could not find file {FILE_NAME}")
return NoneRun it interactively to check that loading works (for now, just print “Loaded ... rows”).
Step 2: Show basic info and statistics
Add functions to inspect the data:
def show_basic_info(df):
print("\n--- Basic Information ---")
print(df.info()) # shows column names and types
def show_summary(df):
print("\n--- Summary Statistics (numeric columns) ---")
print(df.describe()) # count, mean, std, min, max, etc.Now create a simple menu to let the user choose actions.
Step 3: Simple text menu
Add a function:
def main_menu(df):
while True:
print("\nWhat would you like to do?")
print("1) Show first 5 rows")
print("2) Show basic info")
print("3) Show summary statistics")
print("4) Plot a numeric column")
print("5) Quit")
choice = input("Enter your choice (1-5): ").strip()
if choice == "1":
print("\n--- First 5 rows ---")
print(df.head())
elif choice == "2":
show_basic_info(df)
elif choice == "3":
show_summary(df)
elif choice == "4":
plot_column(df)
elif choice == "5":
print("Goodbye!")
break
else:
print("Invalid choice, please try again.")
We still need plot_column(df), which will use matplotlib.
Step 4: Simple plotting
At the top of the file, add:
import matplotlib.pyplot as plt
Now implement plot_column:
def plot_column(df):
print("\nAvailable columns:")
for col in df.columns:
print(f"- {col}")
column_name = input("Enter the name of a numeric column to plot: ").strip()
if column_name not in df.columns:
print(f"Column '{column_name}' does not exist.")
return
if not pd.api.types.is_numeric_dtype(df[column_name]):
print(f"Column '{column_name}' is not numeric and cannot be plotted as a line chart.")
return
print(f"Plotting column '{column_name}'...")
df[column_name].plot(kind="line", title=column_name)
plt.xlabel("Row index")
plt.ylabel(column_name)
plt.show()This:
- Lists available columns.
- Asks the user which column to plot.
- Checks that the column exists and is numeric.
- Plots a simple line chart.
Step 5: Wire everything together
Add a main() that uses all these pieces:
def main():
df = load_data()
if df is None:
return
print("\nPreview of the data:")
print(df.head())
main_menu(df)
if __name__ == "__main__":
main()Run:
python data_explorer.pyTry different menu options and plot a column.
Ideas to extend the data project
Possible improvements:
- Ask the user for the file name instead of hardcoding
data.csv. - Add an option to filter rows, for example:
- “Show rows where age > 25”
- Let the user save filtered data to a new CSV file:
- Use
df.to_csv("filtered.csv", index=False) - Add histogram plots for numeric columns:
df[column_name].plot(kind="hist", bins=10)- Add an option to sort by a chosen column:
df.sort_values(by=column_name)
Picking and Finishing Your Project
To finish this chapter:
- Choose one:
- The notes web app, or
- The CSV data explorer.
- Get the basic version working as shown.
- Add at least one small extension of your own:
- For example, extra route, extra menu option, file saving, styling, etc.
- Run and test:
- Try incorrect input.
- Try edge cases (empty notes, wrong column name, etc.).
This small project is your bridge from individual exercises to real programs that feel useful and complete, even if they are tiny.