Raising Your Own Exceptions
About 18 minutes
Why this matters
Catching errors is half the story. The other half is raising them yourself: when a function is given something it cannot work with, stopping loudly with a clear message is better than quietly returning nonsense.
The idea
def set_volume(level):
if not 0 <= level <= 10:
raise ValueError(f"volume must be 0-10, got {level}")
return level
Pick the built-in error that fits: ValueError (right type, bad value), TypeError (wrong type), KeyError, IndexError… A good message says what was wrong and what was received.
You can also define an error for your own program. Treat these two lines as a recipe for now (Module 8 explains classes):
class OutOfStock(Exception):
pass
Then raise OutOfStock("no apples left") works, and callers can write except OutOfStock:. A bare raise inside an except block re-raises the error you just caught.
Try it
Call set_volume(11) without a try and read the traceback. Then wrap the call in try/except ValueError as err and print err.
Your turn
Write:
validate_age(age): raiseTypeError("age must be a whole number")ifageis not anint; raiseValueError("age must be between 0 and 150")if it is outside 0 to 150; otherwise returnage.- A custom error
OutOfStock(a subclass ofException). take(stock, item, quantity=1):stockis a dictionary of item to count. If there are fewer thanquantity, raiseOutOfStockwith the messageonly 2 apple left, wanted 5(the real numbers and name). Otherwise subtractquantityand return the new count.parse_percent(text): turn"45%"into45. A text without a trailing%or with a non-whole number before it raisesValueError("not a percentage: 'abc'")(showing the text with!r). A value outside 0 to 100 raisesValueErrorwhose message starts withpercentage out of range.
Recap
raise SomeError("message")stops the function and hands the error to the caller.- Choose the closest built-in error, and say what was received in the message.
class MyError(Exception): passcreates an error type of your own.
Common mistakes
- Returning an error code instead of raising, which callers forget to check.
- Vague messages like
"invalid". Include the bad value. - Raising a class that is not an exception, which gives a
TypeError: exceptions must derive from BaseException.