from contextlib import contextmanager
@contextmanagerdefmust_not_fail(label):
try:
yieldexcept Exception as e:
raise RuntimeError(f"{label} failed") from e
try:
with must_not_fail("data load"):
raise ValueError("bad data")
except RuntimeError as e:
print(f"Caught: {e}")
print(f"Original: {e.__cause__}")
# Raise in a generatordefsafe_divide_gen(pairs):
for a, b in pairs:
try:
yield a / b
except ZeroDivisionError:
yieldfloat("inf")
results = list(safe_divide_gen([(10, 2), (5, 0), (9, 3)]))
print(results)
Output
Click "Run" to execute your code
Exceptions raised inside context managers and generators interact with their surrounding protocol (__exit__ and throw()).
Challenge
Try modifying the code above to explore different behaviors. Can you extend the example to handle a new use case?