Catching Multiple Exception Types in Python
🎣 Catching Multiple Exception Types in Python​
In robust Python development, it is often necessary to catch and handle several different types of exceptions that might arise from a single block of code. Python provides flexible and concise syntax to manage multiple exceptions in a single try...except structure.
This article details the three primary methods for catching multiple exceptions, focusing on efficiency and best practice.
1. Method 1: The Single except Block (Using a Tuple)​
The most Pythonic and concise way to handle multiple specific exceptions with the same handling logic is to list them as a tuple following the except keyword.
Code Example: Tuple Catching​
def process_user_input(data):
try:
# Example 1: Failure during type conversion
value = int(data['count'])
# Example 2: Failure during calculation
result = 100 / value
# Catch both KeyError (if 'count' is missing) and ZeroDivisionError
except (KeyError, ZeroDivisionError) as e:
# This single block executes if EITHER exception occurs
print(f"--- Input Error Handled ---")
print(f"Caught {type(e).__name__}: {e}")
return None
except TypeError:
# Other exceptions can still be handled separately
print("Invalid data type provided.")
return None
# Test cases
process_user_input({}) # Triggers KeyError -> Handled
process_user_input({'count': '0'}) # Triggers ZeroDivisionError -> Handled
process_user_input({'count': 'text'}) # Triggers ValueError -> NOT Handled by the tuple
Key Takeaway: If the action you take (logging, cleanup, returning a default value) is identical for a group of exceptions, using a tuple is the cleanest solution.
2. Method 2: Multiple except Blocks (Different Logic)​
If you need distinct, specific handling logic for different exceptions, you must use separate except blocks. This allows you to tailor your response to the specific failure event.
Code Example: Separate Catching​
import os
import requests
def fetch_data_from_file_or_web(source):
if source.startswith('http'):
# Can raise requests.exceptions.Timeout
response = requests.get(source, timeout=2)
response.raise_for_status()
return response.json()
else:
# Can raise FileNotFoundError
with open(source, 'r') as f:
return f.read()
try:
fetch_data_from_file_or_web("https://api.timeout.com")
except requests.exceptions.Timeout:
# 1. Specific logic for network timeouts
print("FATAL: Network request timed out. Retrying later.")
# Log specific network metrics...
except FileNotFoundError:
# 2. Specific logic for missing files
print("WARNING: Local source file missing. Using cached data.")
# Report to a file inventory system...
except Exception as e:
# 3. Final safety net for anything else (like requests.exceptions.HTTPError)
print(f"ANOTHER ERROR: Unhandled exception occurred: {type(e).__name__}")
Key Takeaway: This is the standard pattern when the resolution, logging, or recovery strategy differs significantly between error types.
3. Method 3: Catching by Parent Class (Hierarchy)​
As detailed in the article on exception hierarchy, catching a base class will automatically catch all descendant exceptions. This is the most efficient way to handle a large group of related errors uniformly.
Recall that KeyError and IndexError both inherit from the base class LookupError.
Code Example: Parent Class Catching​
def get_element(collection, key):
# This might fail with a KeyError (if 'collection' is a dict)
# OR an IndexError (if 'collection' is a list)
return collection[key]
try:
get_element(['a', 'b'], 5) # Raises IndexError
get_element({'c': 3}, 'd') # Raises KeyError
# Catching LookupError handles both Index and Key Errors!
except LookupError as e:
print(f"Consolidated handler: Failed to access element. Type: {type(e).__name__}")
except ValueError:
# This is not a LookupError, so it is handled separately
print("Invalid value provided.")
Key Takeaway: Use parent classes like LookupError (for index/key issues), ArithmeticError (for division/overflow issues), or a custom application base class (AppBaseError) to simplify your except blocks.
Summary: Choosing the Right Method​
| Goal | Method | Syntax Example | Best For |
|---|---|---|---|
| Same Logic | Tuple Catching | except (KeyError, IndexError): | Grouping unrelated errors that require the exact same recovery action. |
| Different Logic | Separate Blocks | except KeyError: ... except IndexError: ... | Situations where you need to tailor the response (e.g., logging level, user message) for each specific failure. |
| Related Errors | Parent Class | except LookupError: ... | Handling a known family of errors (e.g., all file I/O errors via except OSError). |
