Handling Errors in Python with Try-Except Blocks
Understanding Exceptions in Python
Exceptions occur when Python encounters unexpected conditions during program execution. These runtime erors disrupt the normal flow of a program and, if left unhandled, will cause the application to terminate abruptly with a traceback message.
Exception handling allows developers to anticipate potential failures and respond gracefully. Instead of crashing, the program can catch the error, take corrective action, and continue execution.
Built-in Exception Types
Python provides numerous built-in exception classes for common error scenarios:
- SyntaxError: The code violates Python's grammar rules
- NameError: Reference to an undefined variable or function
- TypeError: Operation applied to incompatible data types
- ValueError: Argument has the correct type but inappropriate value
- IndexError: Accessing a position beyond sequence bounds
- KeyError: Attempting to retrieve a non-existent dictionary key
- ZeroDivisionError: Division operation with zero as the divisor
The try-except Framework
Python offers four keywords to handle exceptions: try, except, else, and finally.
try:
# Code that might raise an exception
x = int(input("Enter a number: "))
quotient = 100 / x
except ValueError:
# Handle invalid input conversion
print("Invalid input: not a valid integer")
except ZeroDivisionError:
# Handle division by zero
print("Cannot divide by zero")
else:
# Runs only when no exceptions occurred
print(f"Result: {quotient}")
finally:
# Always executes regardless of exceptions
print("Cleanup completed")
Code Flow Explanation
- The
tryblock contains risky operations that may fail - Each
exceptclause specifies which exception type to catch - The
elseblock executes when the try block completes successfully - The
finallyblock runs unconditionally after all other blocks
Practical Examples
Handling User Input Safely
def calculate_average():
try:
numbers = input("Enter numbers separated by commas: ")
values = [float(n.strip()) for n in numbers.split(",")]
average = sum(values) / len(values)
except ValueError as ve:
print(f"Conversion failed: {ve}")
except ZeroDivisionError:
print("No numbers provided")
else:
print(f"Average: {average}")
finally:
print("Operation finished")
calculate_average()
This function converts comma-separated input to floating-point numbers and computes their mean. The exception handlers manage malformed input and empty sequences.
Generic Exception Catching
try:
with open("data.txt", "r") as f:
content = f.read()
lines = content.split("\n")
print(lines[1000])
except Exception as error:
print(f"Something went wrong: {error}")
else:
print("File processed successfully")
finally:
print("Closing resources")
Using except Exception captures any exception type. The as keyword binds the exception instance to a variable for detailed inspection.
Creating Custom Exceptions
class ValidationError(Exception):
def __init__(self, message, field=None):
super().__init__(message)
self.field = field
def validate_age(age_str):
try:
age = int(age_str)
if age < 0:
raise ValidationError("Age cannot be negative", "age")
if age > 150:
raise ValidationError("Age exceeds maximum", "age")
except ValueError:
raise ValidationError("Age must be a number", "age")
return age
try:
user_age = validate_age(input("Enter your age: "))
print(f"Age validated: {user_age}")
except ValidationError as ve:
print(f"Validation failed - {ve}")
if ve.field:
print(f"Problem field: {ve.field}")
Custom exceptions inherit from the base Exception class and can carry additional context like feild names or error codes.
Exception Hierarchy
Python organizes exceptions in a hierarchy. The most general catch-all is BaseException, with Exception being the parent for all non-system-exit exceptions. When catching multiple exception types, always order specific handlers before generic ones:
try:
result = risky_operation()
except FileNotFoundError:
# Handle specific file errors
pass
except RuntimeError:
# Handle runtime errors
pass
except Exception:
# Catch-all for remaining errors
pass
Best Practices
- Catch specific exceptions rather than using bare
except:clauses - Keep try blocks small—only include code that might raise exceptions
- Include context in error messages when re-raising exceptions
- Use
finallyfor cleanup operations like closing files or releasing resources - Avoid suppressing exceptions silently unless intentionally designed to do so