Question
In Python, I know I can catch every exception like this:
try:
# do something that may fail
except:
# do this if anything goes wrong
I also know I can handle specific exceptions separately:
try:
# do something that may fail
except IDontLikeYouException:
# say please
except YouAreTooShortException:
# stand on a ladder
But if I want to perform the same action for two different exceptions, the best approach I can think of is repeating the same code:
try:
# do something that may fail
except IDontLikeYouException:
# say please
except YouAreBeingMeanException:
# say please
Is there a way to catch multiple specific exceptions in a single except block, so both of these exceptions can be handled the same way? For example, is something like this possible?
try:
# do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
# say please
I realize that syntax conflicts with the older form used to bind an exception object, such as:
try:
# do something that may fail
except Exception as e:
# handle the exception
What is the correct Python syntax for catching multiple exceptions in one except block?
Short Answer
By the end of this page, you will understand how to catch multiple exception types in a single Python except block, why Python uses a tuple for this, and how to write clear exception-handling code without repeating yourself.
Concept
In Python, you can catch multiple specific exception types in one except block by putting them inside a tuple.
except (FirstException, SecondException):
...
This is useful when different errors should be handled in the same way. Instead of duplicating code in multiple except blocks, you group the exception types together.
This matters because exception handling is not just about preventing crashes. It is also about:
- making programs more robust
- keeping code readable
- avoiding repeated logic
- handling only the errors you actually expect
A broad except: catches almost everything, which is often too vague and can hide bugs. Catching specific exceptions is usually better because it makes your intent clear.
For example, if both FileNotFoundError and PermissionError should show the same user message, handling them together is a clean solution.
In modern Python, this is the standard approach:
try:
risky_operation()
except (TypeError, ValueError):
print("Invalid input")
If you also need access to the exception object, you can still do that:
try:
risky_operation()
except (TypeError, ValueError) as e:
print(f"Problem: {e}")
So the key idea is:
- one exception type:
except ValueError: - multiple exception types:
except (ValueError, TypeError): - multiple exception types and bind the error:
except (ValueError, TypeError) as e:
Mental Model
Think of an except block like a door scanner checking badges.
- If one specific badge is allowed, you check for one badge.
- If several badges should go through the same door, you give the scanner a list of accepted badges.
In Python, that “list” is written as a tuple of exception classes.
except (ValueError, TypeError):
That means:
“If the error is any one of these types, run this block.”
So instead of building two separate doors that lead to the same room, you make one door that accepts both badges.
Syntax and Examples
Core syntax
Catch one exception:
try:
do_something()
except ValueError:
print("A value error happened")
Catch multiple exceptions in one block:
try:
do_something()
except (ValueError, TypeError):
print("Either a value error or type error happened")
Catch multiple exceptions and keep the error object:
try:
do_something()
except (ValueError, TypeError) as e:
print(f"Handled error: {e}")
Beginner-friendly example
def parse_age(text):
age = int(text)
if age < 0:
raise ValueError("Age cannot be negative")
return age
user_input = "abc"
try:
result = parse_age(user_input)
print(result)
except (ValueError, TypeError):
print("Please enter a valid age")
What this does
int(text)may raiseValueErrorif the string is not numeric.- A
TypeErrorcould happen if the wrong kind of value is passed. - Both errors lead to the same response, so one
exceptblock is enough.
Real built-in example
try:
with open("config.json") as file:
data = file.read()
number = int(data)
except (FileNotFoundError, ValueError):
print("Could not load a valid number from the file")
This catches either:
- the file not existing, or
- the file content not being a valid integer
and handles both cases the same way.
Step by Step Execution
Consider this example:
try:
value = int("hello")
except (ValueError, TypeError) as e:
print("Something went wrong")
print(type(e).__name__)
Step by step
- Python enters the
tryblock. - It evaluates
int("hello"). - The string
"hello"cannot be converted to an integer. - Python raises a
ValueError. - Python checks the
exceptblock:- Is the exception a
ValueError? - Is it a
TypeError?
- Is the exception a
- Since the actual error is
ValueError, the match succeeds. - The exception object is stored in
e. - Python runs the code inside the
exceptblock. - Output becomes:
Something went wrong
ValueError
Another trace
try:
value = int(None)
except (ValueError, TypeError) as e:
print("Something went wrong")
print(type(e).__name__)
This time:
- Python tries
int(None). Noneis not a valid argument here.- Python raises
TypeError. - The same
except (ValueError, TypeError)block matches. - The same handler runs.
This shows why grouping exceptions is useful: different failures can share one response.
Real World Use Cases
Catching multiple exceptions in one block is common when different problems should lead to the same fallback behavior.
User input validation
try:
age = int(user_input)
price = float(price_input)
except (ValueError, TypeError):
print("Please enter valid numbers")
File loading
try:
with open(filename) as f:
content = f.read()
except (FileNotFoundError, PermissionError):
print("Cannot read the file")
API response parsing
try:
user_id = int(response["id"])
except (KeyError, ValueError, TypeError):
print("Bad API data")
Dictionary and conversion logic
try:
count = int(data["count"])
except (KeyError, ValueError):
count = 0
Data processing scripts
When processing many records, you often want to skip invalid rows without stopping the entire script.
for row in rows:
try:
score = int(row["score"])
except (KeyError, ValueError, TypeError):
continue
The grouped exception handler keeps the code short and consistent.
Real Codebase Usage
In real projects, developers usually catch multiple exceptions when the recovery action is identical.
Common patterns
Validation with one fallback
try:
timeout = int(config.get("timeout"))
except (TypeError, ValueError):
timeout = 30
If the config value is missing, wrong, or malformed, the app falls back to a default.
Guarding external input
try:
email = payload["email"].strip()
except (KeyError, AttributeError):
raise ValueError("Invalid payload")
Different low-level failures are turned into one clearer error.
Error logging
try:
result = process(data)
except (ValueError, TypeError) as e:
logger.warning("Invalid data: %s", e)
Early return in web or API code
def get_limit(params):
try:
return int(params.get("limit", 10))
except (TypeError, ValueError):
return 10
Narrow exception scope
A good codebase usually keeps the try block small:
try:
limit = int(raw_limit)
except (TypeError, ValueError):
limit = 10
This is better than wrapping many unrelated lines, because it makes it clear which operation may fail.
Best practice
Catch multiple exceptions together only when:
- they are expected
- they truly need the same response
- the handler remains easy to understand
If the handling differs, use separate except blocks instead.
Common Mistakes
1. Forgetting the parentheses
This is wrong for multiple exceptions:
try:
do_something()
except ValueError, TypeError:
print("Error")
Use a tuple instead:
try:
do_something()
except (ValueError, TypeError):
print("Error")
2. Using bare except: too often
try:
do_something()
except:
print("Something failed")
This catches too much and can hide real bugs.
Better:
try:
do_something()
except (ValueError, TypeError):
print("Invalid input")
3. Catching exceptions that should be handled differently
Broken design:
try:
do_something()
except (FileNotFoundError, PermissionError):
print("File problem")
This is only good if the same response is truly enough. If one should create a file and the other should ask for permissions, separate them.
4. Putting too much code inside try
try:
value = int(text)
save_to_database(value)
send_email(value)
except (ValueError, TypeError):
print("Invalid input")
If save_to_database or send_email raises one of those exceptions, debugging gets harder.
Better:
try:
value = int(text)
except (ValueError, TypeError):
print("Invalid input")
else:
save_to_database(value)
send_email(value)
5. Confusing old and modern syntax
Old Python 2 style often looked like this:
except Exception, e:
Modern Python uses:
except Exception as e:
And for multiple exceptions:
except (ValueError, TypeError) as e:
Comparisons
| Pattern | Syntax | When to use | Notes |
|---|---|---|---|
| Catch everything | except: | Rarely, for very broad cleanup or top-level safety | Can hide bugs |
| Catch one specific exception | except ValueError: | When only one known error should be handled | Clear and explicit |
| Catch multiple exceptions together | except (ValueError, TypeError): | When several errors need the same handling | Best for shared behavior |
| Catch separate exceptions | except ValueError: / except TypeError: | When each error needs different handling | More verbose but clearer |
| Catch and inspect object | except (ValueError, TypeError) as e: | When you need the error message or type | Useful for logging |
Multiple exceptions together vs separate blocks
try:
do_something()
except (ValueError, TypeError):
print("Invalid input")
Use this when both errors mean the same thing to your program.
try:
do_something()
except ValueError:
print("Bad value")
except TypeError:
print("Wrong type")
Use separate blocks when the response should differ.
except: vs except Exception:
except:
- catches almost everything
- usually too broad
except Exception:
- still broad, but more explicit
- often preferred over bare
except:when broad handling is truly needed
Most of the time, catching specific exceptions is the best choice.
Cheat Sheet
# One exception
try:
do_something()
except ValueError:
handle_error()
# Multiple exceptions
try:
do_something()
except (ValueError, TypeError):
handle_error()
# Multiple exceptions with error object
try:
do_something()
except (ValueError, TypeError) as e:
print(e)
Rules
- Use parentheses for multiple exceptions.
- Put exception classes inside the tuple.
- Use
as eif you need the exception object. - Catch specific exceptions whenever possible.
- Use one block only if all listed exceptions should be handled the same way.
Good pattern
try:
value = int(text)
except (TypeError, ValueError):
value = 0
Avoid
except:
pass
This hides errors and makes debugging difficult.
Remember
except ValueError:→ one exceptionexcept (ValueError, TypeError):→ multiple exceptionsexcept (ValueError, TypeError) as e:→ multiple exceptions plus the error object
FAQ
Can Python catch multiple exceptions in one except block?
Yes. Put the exception types in a tuple:
except (ValueError, TypeError):
How do I catch multiple exceptions and access the error message?
Use as e:
except (ValueError, TypeError) as e:
print(e)
Why do I need parentheses around multiple exceptions?
Because Python expects a single object after except, and a tuple groups multiple exception classes into one object.
Is except: the same as catching multiple exceptions?
No. except: catches almost everything, while except (A, B): catches only the listed exception types.
Should I combine exceptions or keep them separate?
Combine them only if the handling is the same. If each exception needs different logic, use separate except blocks.
Does this work with built-in exceptions?
Yes. For example:
except (FileNotFoundError, PermissionError):
What is the modern syntax for binding the exception object?
Use as:
except ValueError as e:
or
except (ValueError, TypeError) as e:
Mini Project
Description
Build a small Python input parser that reads values from a dictionary and safely converts them into usable application settings. This demonstrates how multiple exceptions can be handled together when different failures should lead to the same fallback behavior.
Goal
Create a function that reads a user's age and height from a dictionary, converts them to numbers, and returns safe default values when the input is missing or invalid.
Requirements
- Create a function that accepts a dictionary of user data.
- Read
ageandheightfrom the dictionary. - Convert
ageto an integer andheightto a float. - If a key is missing or a value cannot be converted, use default values instead.
- Use at least one
exceptblock that catches multiple exceptions together.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.