Python Exception Handling: Detailed Overview and Examples
Exception handling in Python is a mechanism to handle errors and exceptional conditions that occur during the execution of a program. It allows you to gracefully manage errors, ensuring that your program can continue running or terminate in a controlled manner.
Basic Concepts
What is an Exception?
An exception is an event that disrupts the normal flow of a program. It typically indicates an error condition or an unusual situation. Examples include division by zero, file not found, or invalid user input.
Try and Except Block
The core structure for handling exceptions is the try
and except
block.
Example: Basic Exception Handling
Multiple Exceptions
Handling Multiple Exceptions
You can handle multiple exceptions using multiple except
blocks.
Example: Handling Multiple Exceptions
try:
result = 10 / 0
except ZeroDivisionError:
print('You cannot divide by zero!')
except FileNotFoundError:
print('The file was not found!')
Handling Multiple Exceptions in a Single Block
You can also handle multiple exceptions in a single except
block.
Example: Single Block for Multiple Exceptions
try:
result = 10 / 0
except (ZeroDivisionError, FileNotFoundError) as e:
print(f'An error occurred: {e}')
The else
and finally
Clauses
Using the else
Clause
The else
clause runs if the try
block did not raise an exception.
Example: Using else
try:
result = 10 / 2
except ZeroDivisionError:
print('You cannot divide by zero!')
else:
print('Division successful!')
print(f'Result is: {result}')
Using the finally
Clause
The finally
clause runs regardless of whether an exception was raised or not. It is often used for cleanup actions.
Example: Using finally
try:
file = open('example.txt', 'r')
data = file.read()
except FileNotFoundError:
print('The file was not found!')
finally:
file.close()
print('File closed.')
Raising Exceptions
Raising Exceptions Manually
You can raise exceptions manually using the raise
keyword.
Example: Raising Exceptions
def divide(a, b):
if b == 0:
raise ValueError('The divisor cannot be zero.')
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(e)
Custom Exceptions
Creating Custom Exceptions
You can define your own exceptions by subclassing the built-in Exception
class.
Example: Custom Exception
class CustomError(Exception):
pass
def do_something():
raise CustomError('This is a custom error.')
try:
do_something()
except CustomError as e:
print(e)
Exception Chaining
Using raise
to Re-raise Exceptions
You can re-raise the original exception in an except
block to preserve the original traceback.
Example: Exception Chaining
def function1():
try:
raise ValueError('An error occurred in function1.')
except ValueError:
print('Handling error in function1.')
raise
try:
function1()
except ValueError:
print('Caught an exception in the outer block.')
Practical Examples
Example 1: Handling User Input
while True:
try:
number = int(input('Enter a number: '))
print(f'You entered: {number}')
break
except ValueError:
print('Invalid input! Please enter a valid integer.')
Example 2: File Operations with Exception Handling
filename = 'data.txt'
try:
with open(filename, 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print(f'The file {filename} was not found.')
except IOError:
print('An I/O error occurred while reading the file.')
Example 3: Handling Multiple Errors
def process_data(data):
try:
# Simulate processing
if not data:
raise ValueError('Data is empty.')
result = int(data) / 2
except ValueError as ve:
print(f'ValueError: {ve}')
except ZeroDivisionError:
print('ZeroDivisionError occurred.')
else:
print(f'Processing result: {result}')
finally:
print('Processing complete.')
process_data('10')
process_data('')
Conclusion
Python's exception handling provides a robust mechanism for managing errors and exceptional conditions that arise during program execution. By using try
, except
, else
, and finally
blocks, you can handle errors gracefully, ensuring that your program can deal with unexpected situations effectively. Custom exceptions and exception chaining further enhance your ability to manage and debug complex error scenarios.