Back to Python Notes
Topic #209

Exception Handling in Python

By the end of this lesson, you will be able to write Python code that detects errors, handles them gracefully without crashing, and cleans up resources using try, except, finally, and custom exceptions.

What it is

Exception handling is a mechanism in Python that allows a program to respond to runtime errors (exceptions) rather than terminating abruptly. When an error occurs, Python raises an exception object. You can "catch" this exception using a try block and define how to handle it in an except block. This separates normal logic from error-handling logic, making code more robust and readable. Key terms include raising (triggering an error), catching (handling an error), and stack trace (the report of where the error occurred).

Why it matters

  • Prevents Crashes: A single unhandled error stops the entire program; handling it allows execution to continue or exit cleanly.
  • User Experience: Instead of showing confusing technical stack traces, you can display friendly messages like "File not found."
  • Resource Management: Ensures files are closed or network connections are terminated even if an error occurs during processing.
  • Debugging Aid: Custom exceptions allow you to create specific error types for your application logic, making debugging easier.

Syntax or steps

The basic structure involves three blocks: 1. try: Contains the code that might raise an exception. 2. except: Contains the code to run if a specific exception occurs. You can have multiple except blocks for different error types. 3. finally: Optional. Contains code that runs no matter what happens (success or failure), typically used for cleanup. You can also use raise to manually trigger an exception, often within a custom exception class.

Example

class InsufficientFundsError(Exception):
    """Custom exception for bank withdrawals."""
    pass

def withdraw(balance, amount):
    try:
        if amount <= 0:
            raise ValueError("Withdrawal amount must be positive.")
        if amount > balance:
            raise InsufficientFundsError(f"Cannot withdraw {amount}. Balance is {balance}.")
        
        new_balance = balance - amount
        print(f"Withdrawal successful. New balance: {new_balance}")
        return new_balance
    
    except ValueError as ve:
        print(f"Input Error: {ve}")
    except InsufficientFundsError as ise:
        print(f"Transaction Failed: {ise}")
    finally:
        print("--- Transaction attempt finished ---")

# Test cases
withdraw(100, 50)   # Success
withdraw(100, 150)  # Custom Exception
withdraw(100, -10)  # Built-in Exception
Explanation: - We define InsufficientFundsError inheriting from Exception. - Inside withdraw, we check conditions. If invalid, we raise specific exceptions. - The except blocks catch these specific errors and print user-friendly messages. - The finally block prints a status message regardless of whether the withdrawal succeeded or failed.

Common mistakes

  • Bare Except: Using just except: catches *all* exceptions, including system-exiting ones like KeyboardInterrupt. Always specify the exception type (e.g., except ValueError:) unless you have a very good reason.
  • Hiding Errors: An empty except block (pass) silently ignores errors, making bugs impossible to find. At minimum, log the error.
  • Catching Too Broadly: Catching Exception instead of specific types (like FileNotFoundError) can mask unexpected bugs. Catch only what you know how to handle.
  • Forgetting Cleanup: Not using finally or context managers (with) when opening files can lead to resource leaks if an error occurs mid-operation.

When to use it

Compare standard control flow with exception handling:
ScenarioUse Control Flow (if/else)Use Exceptions (try/except)
Expected condition (e.g., checking if a key exists)YesNo
Unexpected error (e.g., file missing, network down)NoYes
Validation logic (e.g., input format)OftenIf part of API contract
Use exceptions for exceptional circumstances—things that should rarely happen but require special handling. Use if statements for normal branching logic.

Practice

Guided Exercise: Write a function divide(a, b) that returns a / b. Handle the case where b is zero by printing "Cannot divide by zero" and returning None. Challenge: Modify the function to also handle non-numeric inputs by catching TypeError. Solution Hint: Use except ZeroDivisionError: and except TypeError: blocks.

Quick check

Question: What is the purpose of the finally block? Answer: It executes code that must run regardless of whether an exception was raised or caught, typically used for releasing resources like closing files or database connections.

Summary

Python's exception handling allows programs to react to errors gracefully rather than crashing. By using try, except, and finally, you can separate error logic from main logic, ensuring data integrity and better user experience. Remember to catch specific exceptions and avoid bare except clauses to maintain debuggable code.

Want to go beyond the notes?

Join Coding Now Tech Institute's Python course — live mentorship, real projects, and 100% placement support.

Enroll Now — Free Demo Available

Exception Handling in Python – FAQs

Quick answers about learning Exception Handling in Python in Python.

This free note from Coding Now Tech Institute explains Exception Handling in Python in Python — concept, syntax and worked code examples you can copy, run and revise before interviews.
Yes. Every Python topic on Coding Now Tech Institute, including Exception Handling in Python, is 100% free with no signup required.
With focused practice, most students grasp Exception Handling in Python in 1–3 days from these notes; pairing it with Coding Now Tech Institute's mentor-led course takes you to job-ready depth faster.
Use the code examples in this note, then ask doubts for free on the Coding Now Tech Institute Community (/community) — expert instructors answer within 24 hours.
Call NowEnroll Now