Error Handling
Python try/except vs C# try/catch — exception hierarchy and patterns
Introduction
In this lesson, you'll learn about error handling in Python. Coming from C#, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In C#, you're familiar with python try/except vs c# try/catch — exception hierarchy and patterns.
Python has its own approach to python try/except vs c# try/catch — exception hierarchy and patterns, which we'll explore step by step.
The Python Way
Let's see how Python handles this concept. Here's a typical example:
# try / except / else / finally
try:
data = fetch_data()
result = process_data(data)
except HTTPError as e:
if e.status_code == 404:
print("Not found") # handle specific case inline
else:
print(f"HTTP error: {e}")
except (ValueError, KeyError) as e:
print(f"Data error: {e}") # multiple types in one except
except Exception as e:
print(f"Unexpected: {e}")
raise # re-raise preserves stack trace
else:
print("Success:", result) # runs only if no exception
finally:
release_resources()
# Custom exception hierarchy
class AppError(Exception):
pass
class InsufficientFundsError(AppError):
def __init__(self, amount: float):
super().__init__(f"Insufficient funds: need {amount}")
self.amount = amount
# Exception chaining
try:
parse_config()
except KeyError as e:
raise AppError("bad config") from e # chain: C# has no direct equivalentComparing to C#
Here's how you might have written similar code in C#:
// try / catch / finally
try
{
var data = await FetchDataAsync();
ProcessData(data);
}
catch (HttpRequestException ex) when (ex.StatusCode == 404)
{
Console.WriteLine("Not found"); // when clause = filter
}
catch (HttpRequestException ex)
{
Console.WriteLine("HTTP error: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("Unexpected: " + ex.Message);
throw; // re-throw preserves stack trace
}
finally
{
ReleaseResources();
}
// Custom exception
public class InsufficientFundsException : InvalidOperationException
{
public decimal Amount { get; }
public InsufficientFundsException(decimal amount)
: base($"Insufficient funds: need {amount}") => Amount = amount;
}
// Exception filters
catch (Exception ex) when (logger.LogAndReturn(ex, false)) { }You may be used to different syntax or behavior.
Python has 'else' clause (runs on success) — C# has no equivalent, put success code in try
You may be used to different syntax or behavior.
Python catches multiple types in one except: except (A, B) — C# uses catch (A | B) in newer versions
You may be used to different syntax or behavior.
'raise' (no args) re-raises; 'raise X from Y' chains — C# uses 'throw;' to re-raise
You may be used to different syntax or behavior.
Python exception hierarchy: BaseException → Exception → specific — similar to C# hierarchy
You may be used to different syntax or behavior.
C# 'when' clause = Python if inside except; both are exception filters
Step-by-Step Breakdown
1. Multiple except Clauses
Python allows separate except clauses for different types. For multiple types in one clause, use a tuple: except (A, B) as e.
catch (HttpException ex) { }
catch (TimeoutException ex) { }except HTTPError as e:
handle_http(e)
except TimeoutError as e:
handle_timeout(e)
# or multiple in one:
except (HTTPError, TimeoutError) as e:
handle(e)2. else Clause
Python's 'else' runs only when no exception was raised — cleaner than putting success code at the end of the try block.
try { result = Compute(); successCode(); } catch...try:
result = compute()
except ComputeError as e:
handle(e)
else:
success_code(result) # only runs if no exception3. Re-raising
Bare 'raise' re-raises the current exception, preserving the original stack trace. 'raise X from Y' chains exceptions.
throw; // C# re-raise (not 'throw ex;' — that resets stack)except Exception as e:
log(e)
raise # re-raise same exception
# OR chain:
raise AppError("context") from e4. Custom Exception Hierarchy
Build hierarchies by subclassing. Catching a parent class catches all subclasses. Add custom attributes to exception classes.
class AppException : Exception { }
class ValidationException : AppException { }class AppError(Exception): pass
class ValidationError(AppError):
def __init__(self, field, msg):
super().__init__(msg)
self.field = field
try:
validate()
except AppError as e: # catches ValidationError too
log(e)Common Mistakes
When coming from C#, developers often make these mistakes:
- Python has 'else' clause (runs on success) — C# has no equivalent, put success code in try
- Python catches multiple types in one except: except (A, B) — C# uses catch (A | B) in newer versions
- 'raise' (no args) re-raises; 'raise X from Y' chains — C# uses 'throw;' to re-raise
Key Takeaways
- Python 'else' clause runs only on success — no C# equivalent, put success in try
- Bare 'raise' re-raises with original stack; 'raise X from Y' chains exceptions
- except (A, B) as e catches multiple types; except BaseException catches everything
- Exception hierarchy: subclass for specific errors; catch parent for broad handling