Error Handling & Debugging

1 min read

Catch Bugs, Avoid Crashes, and Write Reliable Code

Even the best-written code can face unexpected situations β€” wrong input, missing files, or network issues. That’s where error handling comes in. Instead of crashing, your program can handle the error gracefully and keep going.


🚫 1. Types of Errors in Python #

πŸ”Ή Syntax Errors #

Happen when Python can’t parse your code.

print("Hello"  # Missing closing parenthesis

πŸ”Ή Runtime Errors (Exceptions) #

Happen while the program is running.

x = 10 / 0  # ZeroDivisionError

πŸ›‘ 2. Using try, except Blocks #

Wrap risky code inside a try block and handle potential errors with except.

try:
    num = int(input("Enter a number: "))
    print(10 / num)
except ZeroDivisionError:
    print("❌ Cannot divide by zero.")
except ValueError:
    print("❌ Please enter a valid number.")

πŸ”„ 3. else and finally in Try Blocks #

βœ… else: Runs if no exception occurs #

πŸ”’ finally: Always runs (good for cleanup) #

try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("❌ File not found!")
else:
    print("πŸ“„ File read successfully.")
finally:
    print("πŸ”’ Closing file (if opened).")
    try:
        file.close()
    except:
        pass

🧠 4. Raising Your Own Exceptions #

Sometimes you need to create your own error messages.

age = int(input("Enter your age: "))
if age < 0:
    raise ValueError("Age cannot be negative!")

🧰 5. Debugging Tools in Python #

πŸ§ͺ Using print() for Debugging (Old School but Effective) #

x = 5
y = 0
print("Debug: x =", x, " y =", y)
print(x / y)  # You'll catch it before crash

🐞 Using pdb (Python Debugger) #

import pdb

pdb.set_trace()  # Execution will pause here
x = 10
y = 5
z = x + y
print(z)

Use commands like:

  • n: next line
  • c: continue
  • q: quit

⚠️ Common Exceptions #

ExceptionTrigger Example
ZeroDivisionErrorDivision by zero
ValueErrorConverting string to int (int("abc"))
FileNotFoundErrorOpening non-existent file
TypeErrorAdding string to integer
KeyErrorAccessing missing dictionary key

🧠 Real-World Use Case: Login Authenticator with Error Handling #

Let’s create a CLI app that:

  • Takes username and password
  • Handles incorrect input
  • Locks out after 3 failed attempts

βœ… Code Example #

def login_system():
    correct_username = "admin"
    correct_password = "1234"
    attempts = 3

    while attempts > 0:
        try:
            username = input("Username: ")
            password = input("Password: ")

            if not username or not password:
                raise ValueError("Fields cannot be empty!")

            if username == correct_username and password == correct_password:
                print("βœ… Login successful!")
                return
            else:
                attempts -= 1
                print(f"❌ Invalid credentials. Attempts left: {attempts}")

        except ValueError as e:
            print("⚠️", e)

    print("🚫 Too many failed attempts. Account locked.")

# Run it
login_system()

πŸ–₯ Output Example #

Username: admin
Password: wrong
❌ Invalid credentials. Attempts left: 2
Username: 
Password: 1234
⚠️ Fields cannot be empty!
Username: admin
Password: 1234
βœ… Login successful!

πŸ” Key Takeaways #

FeaturePurpose
try...exceptCatch and handle runtime errors
finallyCleanup, like closing files
raiseManually trigger exceptions
pdbStep-by-step code investigation
Best PracticeAlways validate user inputs

πŸ”š Wrap Up #

You can’t predict every problem your code may face β€” but you can plan how it responds to them. Error handling makes your apps smarter, safer, and way more user-friendly.


πŸ”œ Up Next: #

Modules & Code Organization
Learn how to break your code into reusable modules, import them smartly, and manage larger projects easily β€” with a Library Book Management App example.

Updated on June 9, 2025