The Art of Exception Handling in Python: Using raise...from
This article explains how Python's raise...from statement can be used to link exceptions, providing clear examples that demonstrate basic usage, function integration, file handling, multi‑level chaining, network errors, class methods, database queries, serialization, loops, and decorators to improve error reporting and debugging.
🌟 The Art of Exception Handling in Python 🌟
In Python, handling errors gracefully improves code robustness and makes debugging easier. The raise...from statement lets you raise an exception while explicitly linking it to another, creating an exception chain that conveys cause and context.
What is raise...from?
The raise statement triggers an exception. By adding from followed by another exception, you indicate that the new exception was caused by the original one, establishing a causal relationship.
Example Code
Below are ten examples illustrating how raise...from works in various scenarios. Each snippet is wrapped in a try‑except block to capture and print the exception and its cause.
Example 1: Basic usage – raise an exception and link it
try:
raise ValueError("Something went wrong") from ZeroDivisionError("Divided by zero")
except Exception as e:
print(f"Cause: {e.__cause__}")
print(f"Context: {e.__context__}")
print(f"{e}")Example 2: Using inside a function
def risky_operation():
try:
result = 1 / 0
except ZeroDivisionError as zde:
raise ValueError("Cannot perform operation") from zde
try:
risky_operation()
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 3: Handling a missing file
try:
with open("nonexistent_file.txt") as f:
pass
except FileNotFoundError as fnfe:
raise IOError("Failed to read file") from fnfeExample 4: Multi‑level exception linking
try:
raise IndexError("List index out of range") from KeyError("Key not found")
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 5: Network request failure
import requests
def fetch_url(url):
try:
response = requests.get(url)
response.raise_for_status()
except requests.exceptions.HTTPError as http_err:
raise IOError("Failed to fetch URL") from http_err
try:
fetch_url("http://example.com/nonexistent")
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 6: In a class method
class CustomException(Exception):
pass
class MyClass:
def __init__(self):
self.value = None
def set_value(self, val):
if not isinstance(val, int):
raise TypeError("Value must be an integer") from ValueError("Invalid value type")
obj = MyClass()
try:
obj.set_value("not an int")
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 7: Database query error
class DBHandler:
def query(self, sql):
# Simulate a database error
raise Exception("Database error")
handler = DBHandler()
try:
handler.query("SELECT * FROM table")
except Exception as db_err:
raise RuntimeError("Database query failed") from db_errExample 8: Serialization problem
import json
def serialize(data):
try:
return json.dumps(data)
except TypeError as te:
raise ValueError("Data cannot be serialized") from te
try:
serialize({"key": object()})
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 9: Using in a loop
for i in range(-1, 2):
try:
if i < 0:
raise ValueError("Negative number") from IndexError("Index out of bounds")
elif i == 0:
raise ZeroDivisionError("Divided by zero")
else:
print("Positive number")
except Exception as e:
print(f"{e} caused by {e.__cause__}")Example 10: In a decorator
def exception_decorator(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as inner_e:
raise RuntimeError("Function execution failed") from inner_e
return wrapper
@exception_decorator
def decorated_function():
raise ValueError("Decorated function error")
try:
decorated_function()
except Exception as e:
print(f"{e} caused by {e.__cause__}")Run Results
The print statements in the examples output the exception messages along with their linked causes, demonstrating how raise...from builds an exception chain that aids debugging and error reporting.
Conclusion
Using raise...from lets you explicitly express causal relationships between exceptions, which is especially valuable in complex error‑handling scenarios. Mastering this feature makes Python code more robust, maintainable, and easier to debug.
💡 Tip: While raise...from enriches logs with context, avoid overusing it to prevent overly complex exception traces.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
