Explain Codes LogoExplain Codes Logo

Manually raising (throwing) an exception in Python

python
exception-handling
custom-exceptions
debugging
Alex KataevbyAlex Kataev·Aug 4, 2024
TLDR

Create a Python exception with the raise (+) exception type:

raise ValueError("Invalid input")

Alternatively, without additional information:

raise ValueError

This halts code execution immediately and can be dealt with try...except constructs.

Use the proper exception

Although you can initiate an exception easily, selecting the proper one is essential for maintainable code:

  • Use ValueError when the function's expectations aren't met by the input.
  • If the argument is of an incorrect type, use the TypeError.
  • When a search in a collection fail, go for KeyError or IndexError.
  • Use AssertionError when the expected condition turns out to be false.
  • For an unrecoverable error situation, use SystemExit to exit the script smoothly.

Remember, using specific exceptions helps debugging process by letting developers understand and fix the issue quickly.

Custom exceptions? Yes, you can!

Creating custom exceptions:

  1. Start by subclassing an existing exception class:
    class CustomError(Exception): """Raised when you've got your own error club."""
  2. Add extra context by overriding __init__:
    class CustomError(Exception): def __init__(self, value, message="It's custom, baby!"): self.value = value self.message = message super().__init__(self.message)
  3. Be sure to represent and handle them precisely in try...except:
    try: raise CustomError(42) # Hitchhiker's guide says the answer was always 42 except CustomError as e: print(f"A custom error with value {e.value} occurred: {e.message}")
    The name of your custom exception class can be your personal code-warning!

Exception chaining: Like a detective story!

Use exception chaining to keep the original error story intact. This helps significantly with debugging and understanding the root causes:

try: # Looks fine until... operation_that_may_fail() # Oh no! It was a trap! except ValueError as e: # Plot twist! Came out of nowhere. raise RuntimeError("This thing is bigger than we thought!") from e

Doing this keeps the original traceback info intact, rendering Sherlock Holmes level details to trace the bugs.

Practices to swear by when raising exceptions

  • Convey the context. Always supply a message:
    raise ValueError("Hello? Is it 'me' you're looking for? Because 'me' is greater than 0.")
  • Inside an except block, simply use raise to keep the history:
    try: # Just a simpleton function, what could go wrong? problematic_function() except Exception: log_error() # Always keep a tab on your problems raise # "Oops, I did it again" - Python, probably.
  • Make a group exception catch with except (TypeError, ValueError).
  • Log before you relaunch to keep a record for solving mysteries:
    try: # This one is kinda risky risky_operation() except Exception as e: # Note it down, just in case log_error(e) raise # Courageously retrying "I volunteer as tribute!"
  • Format and customise exception strings with .format() for readability and to include variables: "Just {'cause'} we felt like it".