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 |