🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

【Copy-Paste to Run】Let's Build a Simple To-Do List App in Python! (Text-Based)

To run Python from the command prompt or PowerShell on your PC, you need to download and install Python.
If you haven’t installed it yet, please refer to the article Setting Up Python and Development Environment to install Python.

Hello! I had zero programming knowledge just a few months ago, and now I'm sharing what I learned while building websites with AI.

This time, we'll create a "To-Do List App" in Python, which I highly recommend as a first step in learning to program. The goal of this article is simple: for you to experience the thrill of "My own program is running!"

Let's leave the difficult theory for later! First, let's play with code that you can copy and paste to get a feel for, "Oh, so that's how it works!" I'll explain the technical terms in a super simple way based on my own stumbling blocks, so don't worry.


Let's Run the Final Product First!

Seeing is believing! Let's run the finished version of the To-Do list app first. Copy all the code below, create a file named todo.py, and paste it in.


# -*- coding: utf-8 -*-

TASKS_FILE = "tasks.txt"

def load_tasks():
    """Function to load tasks from a file"""
    try:
        with open(TASKS_FILE, "r", encoding="utf-8") as f:
            # Use strip() to remove the newline character at the end of each line
            tasks = [line.strip() for line in f.readlines()]
    except FileNotFoundError:
        # If the file doesn't exist, return an empty list
        tasks = []
    return tasks

def save_tasks(tasks):
    """Function to save tasks to a file"""
    with open(TASKS_FILE, "w", encoding="utf-8") as f:
        # Add a newline after each task before writing
        for task in tasks:
            f.write(task + "\n")

def list_tasks(tasks):
    """Function to list all tasks"""
    if not tasks:
        print("✅ No tasks yet.")
        return
    
    print("--- To-Do List ---")
    # Use enumerate to get both the index (number) and the task
    for i, task in enumerate(tasks):
        print(f"{i + 1}: {task}")
    print("------------------")

def add_task(tasks):
    """Function to add a task"""
    task = input("Enter the task to add: ")
    if task:
        tasks.append(task)
        save_tasks(tasks)
        print(f"✨ Task '{task}' added.")
    else:
        print("⚠️ No task entered.")

def delete_task(tasks):
    """Function to delete a task"""
    list_tasks(tasks)
    if not tasks:
        return
        
    try:
        # Let the user choose a task by its number
        num_str = input("Enter the number of the task to delete: ")
        num = int(num_str)
        
        # Adjust because the user counts from 1, but the list index starts at 0
        if 1 <= num <= len(tasks):
            removed_task = tasks.pop(num - 1)
            save_tasks(tasks)
            print(f"🗑️ Task '{removed_task}' deleted.")
        else:
            print("⚠️ No task with that number exists.")
            
    except ValueError:
        # Error handling for non-numeric input
        print("⚠️ Please enter a valid number.")

def main():
    """Main function to run the process"""
    tasks = load_tasks()
    
    while True:
        print("\nWhat would you like to do?")
        command = input("1:List, 2:Add, 3:Delete, 9:Exit > ")
        
        if command == "1":
            list_tasks(tasks)
        elif command == "2":
            add_task(tasks)
        elif command == "3":
            delete_task(tasks)
        elif command == "9":
            print("👋 Exiting the app. Great work!")
            break
        else:
            print("⚠️ Please enter 1, 2, 3, or 9.")

if __name__ == "__main__":
    main()
        

Once saved, open your terminal (or Command Prompt/PowerShell on Windows), navigate to the directory where you saved the file, and run the following command:


python todo.py
        

How did it go? Did it ask "What would you like to do?" Try entering "2" to add a task, "1" to see the list, and "3" to delete a task. You can exit the app by entering "9". Amazing, it's already a proper app!

From here, let's unravel what this magic spell (the code) is actually doing.


Step 1: A Super Simple Version with Only "Add" and "List"

Trying to understand everything at once can be overwhelming. Let's start with a much simpler version of the code, focusing only on the heart of the app: adding and listing tasks.


# Prepare an empty list (like an array) to store tasks
tasks = []

# Loop indefinitely
while True:
    print("\nWhat would you like to do?")
    command = input("1:List, 2:Add, 9:Exit > ")

    if command == "1":
        print("--- To-Do List ---")
        for task in tasks:
            print(task)
        print("------------------")
    
    elif command == "2":
        task = input("Enter the task to add: ")
        tasks.append(task)
        print(f"✨ Task '{task}' added.")

    elif command == "9":
        print("👋 Exiting the app.")
        break # Exit the loop

    else:
        print("⚠️ Please enter 1, 2, or 9.")
        

This short piece of code is packed with programming fundamentals.


Step 2: Adding a "Delete" Function and Error Handling

Next, let's make it possible to delete added tasks. Just deleting isn't very user-friendly, so we'll let the user choose which task to delete by number. We're leveling up a bit here!


# ... (Replace the `if command == "1":` part from Step 1's code with the following) ...

    if command == "1":
        print("--- To-Do List ---")
        # Using enumerate gets you the index and the item at the same time
        for i, task in enumerate(tasks):
            # i starts from 0, so add 1 for display
            print(f"{i + 1}: {task}") 
        print("------------------")

# ... (Add the following after `elif command == "2":` from Step 1's code) ...
    
    elif command == "3": # Add delete functionality
        # First, display the current list to make it easier for the user to choose
        for i, task in enumerate(tasks):
            print(f"{i + 1}: {task}")

        try:
            num_str = input("Enter the number of the task to delete: ")
            num = int(num_str) # Convert the input string to a number

            # pop() removes the element at the specified index from the list
            removed_task = tasks.pop(num - 1) 
            print(f"🗑️ Task '{removed_task}' deleted.")
        
        except ValueError:
            print("⚠️ Please enter a valid number.")
        except IndexError:
            print("⚠️ No task with that number exists.")
        

A few new points have come up.

It's a golden rule that "users won't operate the way the developer expects." By including error handling like this, you can prevent your app from crashing unexpectedly and create a more user-friendly and robust program.


Step 3: Saving Data to a File So It Doesn't Disappear

Our current app has a major weakness. Once you close the program, all the added tasks disappear. That makes it useless as a to-do list, right? So, let's add a feature to save tasks to a file and load them the next time it starts.


# Decide on a filename
TASKS_FILE = "tasks.txt"

# --- Function Definitions ---
def load_tasks():
    try:
        # "r" is for read mode
        with open(TASKS_FILE, "r", encoding="utf-8") as f:
            # readlines() reads all lines into a list, and strip() removes newline characters
            tasks = [line.strip() for line in f.readlines()]
    except FileNotFoundError:
        # This will error out the first time or if the file is missing, so return an empty list
        tasks = []
    return tasks

def save_tasks(tasks):
    # "w" is for write mode. If the file doesn't exist, it will be created.
    with open(TASKS_FILE, "w", encoding="utf-8") as f:
        for task in tasks:
            # When writing to a file, add a newline character (\n) to the end of each task
            f.write(task + "\n")

# --- Main Process ---
# When the app starts, first load the tasks from the file
tasks = load_tasks()

# Every time a task is added or deleted, change it to call save_tasks(tasks)
# (Refer to the complete code at the beginning)
        

The key point here is "file I/O" (Input/Output).

Finally, as shown in the complete code at the beginning, grouping blocks of processing into "functions" using def (this is called refactoring) makes the code much cleaner and easier to understand. When your code starts getting long, making a habit of organizing it into boxes (functions) for each feature will make your future self's life much easier.


Conclusion: If It Runs, You Win! And On to the Next Step

Great job! You now have the power to create your own To-Do list app in Python. The most important thing is not to understand everything perfectly, but to "just try running it, even if it's by copy-pasting." Having something that works and then tweaking it little by little, experimenting with "what happens if I change this?", is the fastest path to improvement, as I've experienced firsthand.

Errors are not scary; they are hints to make your program better. Even if you can't read an error message, you can just paste it into an AI and ask, "What does this error mean, and how can I fix it?" and it will usually give you a solution.

Feel free to add features like "edit task" or "check off completed tasks" to the app you built today, and grow it into your own ultimate To-Do list!

Next Steps

Now that you can make a basic app, why not try tackling calculations next? Here's how to build a simple calculator app that can perform the four basic arithmetic operations.

Let's Build a Calculator App in Python (Arithmetic Operations)