In the final lesson of our Python from Zero course, we polish the To-Do App: adding numbered output, better formatting, and preparing the ground for CSV import/export.
Congratulations! You’ve reached the final step of the Python from Zero series 🎉. So far, our To-Do App can add, edit, remove, and persist tasks in a .txt file. In this lesson we’ll do some final polishing:
- Add task numbering in the display.
- Improve formatting for better readability.
- Set up the code so it’s easier to switch to CSV import/export later.
1) Numbering and Formatting
Our previous printout was simple. Let’s add numbering and a header line for clarity:
def print_tasks(tasks):
if not tasks:
print("\\n[No tasks yet]\\n")
return
print("\\n=== Current To-Do List ===")
for i, t in enumerate(tasks, start=1):
print(f"{i:2d}. {t}")
print("===========================")
This gives output like:
=== Current To-Do List ===
1. Buy milk
2. Finish project
3. Read a book
===========================
2) Preparing for CSV
Right now we save tasks as plain text. To move toward CSV (comma-separated values), we can define a task as a small dictionary or tuple. For example:
import csv
def save_tasks_csv(tasks, filename="tasks.csv"):
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
for task in tasks:
writer.writerow([task])
def load_tasks_csv(filename="tasks.csv"):
tasks = []
try:
with open(filename, "r", newline="", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
if row:
tasks.append(row[0])
except FileNotFoundError:
pass
return tasks
Even though we’re still using simple strings, this structure makes it easy to expand later (e.g., add columns for status, priority, or due date).
3) Final Polished To-Do App
from typing import List
import csv
FILENAME = "tasks.csv"
# ---------- Persistence Layer (CSV-ready) ----------
def load_tasks(filename: str = FILENAME) -> List[str]:
tasks: List[str] = []
try:
with open(filename, "r", newline="", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
if row:
tasks.append(row[0])
except FileNotFoundError:
pass
return tasks
def save_tasks(tasks: List[str], filename: str = FILENAME) -> None:
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
for task in tasks:
writer.writerow([task])
# ---------- Helpers ----------
def print_tasks(tasks: List[str]) -> None:
if not tasks:
print("\\n[No tasks yet]\\n")
return
print("\\n=== Current To-Do List ===")
for i, t in enumerate(tasks, start=1):
print(f"{i:2d}. {t}")
print("===========================")
def add_task(tasks: List[str]) -> None:
new_task = input("Enter new task: ").strip()
if not new_task:
print("Empty task not added.")
return
tasks.append(new_task)
save_tasks(tasks)
print("Task added and saved.")
def remove_task(tasks: List[str]) -> None:
print_tasks(tasks)
if not tasks:
return
idx_str = input("Enter the task number to remove: ").strip()
if not idx_str.isdigit():
print("Please enter a valid number.")
return
idx = int(idx_str)
if 1 <= idx <= len(tasks):
removed = tasks.pop(idx - 1)
save_tasks(tasks)
print(f"Removed: '{removed}' (saved).")
else:
print("Invalid task number.")
# ---------- CLI ----------
def main() -> None:
print("=== Step 10.7 — Final Project Polishing ===")
tasks = load_tasks()
print(f"Loaded {len(tasks)} task(s).")
while True:
print_tasks(tasks)
print("Choose an action:")
print("[a] Add [r] Remove [q] Quit")
choice = input("> ").strip().lower()
if choice == "a":
add_task(tasks)
elif choice == "r":
remove_task(tasks)
elif choice == "q":
save_tasks(tasks)
print("Tasks saved. Goodbye!")
break
else:
print("Unknown option. Please choose a, r, or q.")
if __name__ == "__main__":
main()
4) Wrap-Up
With these final touches, our To-Do App is:
- Readable — numbered and formatted task list.
- Persistent — tasks are saved between sessions.
- Extensible — ready for CSV, JSON, or even databases.
This concludes the Python from Zero journey 🚀. You now have the foundations to move on to larger projects: from simple command-line tools to structured applications.
Homework:
- Extend the CSV format to include a second column (e.g., task status: “done”/”pending”).
- Format the output so completed tasks show a checkmark ✓.
- Experiment with JSON saving instead of CSV.
- Think of one personal project where you could apply this structure.
