A custom exception is a class that inherits from Exception. Its name says exactly what went wrong, and it can carry extra data that the code catching it can use.
The program
python
class InsufficientFundsError(Exception): def __init__(self, balance, amount): self.balance = balance self.amount = amount self.shortfall = amount - balance super().__init__( f"cannot withdraw {amount:.2f}, balance is {balance:.2f}" ) def withdraw(balance, amount): if amount > balance: raise InsufficientFundsError(balance, amount) return balance - amount balance = 120.00 for amount in [50.00, 200.00]: try: balance = withdraw(balance, amount) print(f"Withdrew {amount:.2f}. New balance: {balance:.2f}") except InsufficientFundsError as error: print("Refused:", error) print(f"You need {error.shortfall:.2f} more.")
output
Withdrew 50.00. New balance: 70.00 Refused: cannot withdraw 200.00, balance is 70.00 You need 130.00 more.
How it works
class InsufficientFundsError(Exception)makes a new exception type. Because it inherits fromException, it works withraiseandexceptlike any built-in exception.__init__saves the extra fields on the object:balance,amountandshortfall.super().__init__(message)passes the message toException, soprint(error)and the traceback show it.except InsufficientFundsErrorcatches only this error. AValueErroror aTypeErrorfrom another bug would not be caught here by mistake.- The caller reads
error.shortfallto give a useful answer, without having to parse the message text. - Exception class names end in
Errorby convention, likeValueErrorandKeyError.
A family of errors
Give your exceptions a shared base class. Then the caller can catch one specific error, or all of them at once:
python
class BankError(Exception): pass class InsufficientFundsError(BankError): pass class AccountLockedError(BankError): pass for error_type in [InsufficientFundsError, AccountLockedError]: try: raise error_type("example") except BankError as error: print(f"Caught {type(error).__name__}")
output
Caught InsufficientFundsError Caught AccountLockedError
except BankError catches both, because each one is a BankError. The bank account class is a full example where an error like this fits.
Related programs: Raise an exception.