Error Handling

Try, Except, Else, Finally

What Is Exception Handling?

In Python, exceptions occur when an error disrupts the normal flow of a program (like dividing by zero or opening a non-existent file). Instead of crashing, you can catch and handle these errors using try and except.

Basic Syntax

try:
# Code that might raise an exception
except ExceptionType:
# Code that runs if an exception occurs
else:
# Code that runs if no exception occurs
finally:
# Code that always runs (no matter what)

try Block

The try block wraps code that might raise an error.

try:
result = 10 / 0

except Block

Catches and handles the error. You can catch specific errors or use a generic except.

except ZeroDivisionError:
print(“You can’t divide by zero.”)

Example:

try:
num = int(input(“Enter a number: “))
print(100 / num)
except ValueError:
print(“That’s not a number.”)
except ZeroDivisionError:
print(“Can’t divide by zero.”)

else Block

Runs only if no exception was raised in the try block.

try:
result = 10 / 2
except ZeroDivisionError:
print(“Math error.”)
else:
print(“Division successful:”, result)

finally Block

Runs no matter what — whether an exception occurred or not. Great for cleanup code like closing files or releasing resources.

try:
f = open(“data.txt”)
data = f.read()
except FileNotFoundError:
print(“File not found.”)
finally:
print(“Done attempting file operation.”)
if ‘f’ in locals():
f.close()

Catching Multiple Exceptions

try:
# code
except (TypeError, ValueError):
print(“Type or Value error occurred.”)

Catching Any Exception (Not Always Recommended)

try:
# risky code
except Exception as e:
print(“An error occurred:”, e)

Use this only when you want to log or handle all errors generically — it can hide bugs if misused.

Summary:

Block Purpose
try Code that might raise an exception
except Handles specific exceptions (errors)
else Runs only if no exceptions occurred
finally Always executes (for cleanup actions)

Common exception types

Common Exception Types in Python

1. SyntaxError

  • Raised when the parser encounters a syntax mistake.

if True print(“Hello”) # Missing colon

2. NameError

  • Raised when a variable or function name is not defined.

print(age) # if `age` is not defined

3. TypeError

  • Raised when an operation or function is applied to the wrong data type.

print(“Age: ” + 25) # Mixing str and int

4. ValueError

  • Raised when a function gets the right type, but an inappropriate value.

int(“abc”) # Can’t convert string to integer

5. IndexError

  • Raised when trying to access an invalid index in a list or string.

numbers = [1, 2, 3]
print(numbers[5])

6. KeyError

  • Raised when a key is not found in a dictionary.

info = {“name”: “Alice”}
print(info[“age”]) # ‘age’ doesn’t exist

7. AttributeError

  • Raised when a variable doesn’t have a referenced method or attribute.

x = 10
x.append(5) # int doesn’t have append()

8. ZeroDivisionError

  • Raised when dividing by zero.

print(5 / 0)

9. ImportError / ModuleNotFoundError

  • Raised when an import fails or the module is missing.

import non_existent_module

10. FileNotFoundError

  • Raised when a file operation fails due to a missing file.

open(“missing_file.txt”)

11. IOError / OSError

  • General input/output errors (file read/write, permissions, etc.).

with open(“/protected/file.txt”, “r”) as f:

12. IndentationError

  • Raised when there’s a problem with indentation levels.

def say_hi():
print(“Hello”) # not indented correctly

13. RuntimeError

  • A generic error when no other exception type applies but something unexpected goes wrong.

14. StopIteration

  • Raised by iterators when there are no more items.

it = iter([1, 2])
next(it)
next(it)
next(it) # raises StopIteration

15. AssertionError

  • Raised when an assert statement fails.

assert 2 + 2 == 5, “Math is broken!”

Tips for Handling

  • Catch specific exceptions to avoid hiding bugs.
  • Use try-except-else-finally for clear, safe error handling.
  • Use Exception class to handle unexpected errors only when needed.

Custom exceptions

What Are Custom Exceptions?

Python allows you to create your own exception classes, giving you more control and clarity when things go wrong in your programs — especially in larger applications or libraries.

Rather than relying solely on built-in exceptions like ValueError or TypeError, you can define custom exceptions tailored to your specific logic or business rules.

Defining a Custom Exception

To create one, define a new class that inherits from Exception or a subclass of it:

class MyCustomError(Exception):
“””A custom exception for specific application logic.”””
pass

Example: Using a Custom Exception

class NegativeAgeError(Exception):
“””Raised when a negative age is provided.”””
def __init__(self, age):
super().__init__(f”Invalid age: {age}. Age cannot be negative.”)

def set_age(age):
if age < 0:
raise NegativeAgeError(age)
print(f”Age set to {age}”)

set_age(-5)

Output:

Traceback (most recent call last):

NegativeAgeError: Invalid age: -5. Age cannot be negative.

Why Use Custom Exceptions?

  • More meaningful error messages.
  • Easier to handle specific problems in try/except blocks.
  • Cleaner error management in larger or shared codebases.
  • Enables domain-specific logic (e.g., InsufficientBalance, InvalidConfiguration, etc.).

Custom Exception Hierarchy (Optional)

You can create a base exception class for your application and then extend it:

class AppError(Exception):
“””Base class for all custom exceptions in the app.”””
pass

class InvalidInputError(AppError):
pass

class DataNotFoundError(AppError):
pass

This way, you can catch all related errors at once:

try:
# risky operation
raise InvalidInputError(“Bad data format”)
except AppError as e:
print(“Application error:”, e)

Best Practices

  • Inherit from Exception, not BaseException.
  • Provide clear docstrings and custom messages.
  • Use exception names that describe the problem (e.g., EmailFormatError).
  • Consider organizing exceptions in a separate module for larger projects.

Summary:

Feature Description
Purpose Handle application-specific errors with clear semantics
How to define class CustomError(Exception): pass
or subclass another built-in exception
Benefits Improved code clarity, better error categorization, and more precise error handling
Example use cases NegativeAgeError,
InvalidEmailError,
PermissionDeniedError,
OutOfStockError

 

Leave a Comment