Explain Codes LogoExplain Codes Logo

How to use "raise" keyword in Python

python
exception-handling
best-practices
error-propagation
Anton ShumikhinbyAnton Shumikhin·Dec 7, 2024
TLDR

raise in Python denotes an excavation where we dig up or generate an exception intentionally. After raise, place the exception class followed by particulars of the anomaly. Example:

if not user.is_admin: raise PermissionError('Breaking news: user forgot admin privileges.')

In this snippet, the raise keyword hauls up a PermissionError if the user is performing admin tasks without the privileges.

Creating custom exceptions

raise is a beacon for exception creativity — allowing you to develop custom exceptions tailored for your problems. This aids in building libraries or working with specific rules. Behold the creation of a custom error below for a bank application:

class InsufficientFundsError(Exception): def __init__(self, balance, amount): message = f"Hold up! Withdrawal of {amount} bucks but only {balance} in the bank!" super().__init__(message) # Imagine this function as an ATM def withdraw(balance, amount): # If you got less than what you want to withdraw if amount > balance: # Here we go, custom error to the rescue raise InsufficientFundsError(balance, amount) # Decrease the balance balance -= amount return balance

The custom exception offers more acute error handling and clearer debugging information for the developers.

Re-raising exceptions

There is more to raising exceptions. We can use it to propagate exceptions with raise from. It retains and shows the context of the original error. With it, we can demonstrate error scenarios like a nested matryoshka of problems.

try: process_file() except FileNotFoundError as e: raise RuntimeError("Where on Earth is the file?") from e

raise can also revive a caught exception and send it on its way up the call stack:

try: risky_operation() except SomeError: log_error() # Logs the error detail for future reference, like a fortune teller predicting exceptions raise # Brings back the exception from oblivion

Enforcing rules

raise is your loyal sentinel, refusing entry to any unwanted conditions:

# this isn't the wild west, we need rules here def set_age(age): # if age isn't within 0 and 150 if not 0 < age < 150: raise ValueError("Age must be between 0 and 150.") # Whoa there cowboy, that's not an age # Proceed with rest of the function

Holistic error handling

Python encourages us to master exceptions and follow best practices, just like how a wise guru advises you about the path of enlightenment:

Specific Exceptions

Aim for precise exceptions rather than casting a giant net using a generalized Exception type. It aligns error diagnosis and also adds clarity:

try: operation_that_might_throw_ioerror() except IOError as e: handle_the_specific_ioerror_case(e)

Resource Cleanup

Use finally to clean up resources like dishes after dinner (or file handlers or database connections after use):

try: open_file() # opens a file read_file() # reads the file except IOError as e: handle_error(e) # handles the error finally: close_file() # there ain't a mess if you clean up instantly

Clarity with else

Use else to run cleaning service only when no dirt (exceptions) are found:

try: paint_house() except Exception as error: handle_error(error) else: feel_accomplished()

Finally, the with statement (context manager) can help deal with exceptions by handling the setup and teardown of resources:

with open('notebook.txt', 'r') as f: notes = f.read() # even if read() flames up, file gets auto-closed by context manager