raise / Custom Exception Classes
The raise keyword intentionally raises an exception. By defining custom exception classes, you can clearly represent errors specific to a library or your own module. Custom exception classes must always inherit from Exception or an appropriate subclass of it. Avoid inheriting directly from BaseException except for special use cases.
Syntax
# Raise an exception
raise ExceptionClass("message")
# Chain a new exception with a cause
raise NewException from OriginalException
# Re-raise the current exception (inside an except block)
raise
# Define a custom exception class
class MyError(Exception):
pass
class MyDetailedError(Exception):
def __init__(self, message, code):
super().__init__(message)
self.code = code
Syntax / Class Reference
| Syntax / Class | Description |
|---|---|
| raise Exception(msg) | Raises an exception. Used outside an except block. |
| raise | Re-raises the current exception. Can only be used inside an except block. |
| raise NewException from OldException | Converts an exception to another while preserving the original cause. |
| class MyError(Exception) | Defines a custom exception class that inherits from Exception. |
| super().__init__(msg) | Calls the parent class's __init__ to set the error message. |
Sample Code
# raise: basic exception raising
def divide(a, b):
if b == 0:
raise ZeroDivisionError("Division by zero is not allowed")
return a / b
try:
divide(10, 0)
except ZeroDivisionError as e:
print(e) # Division by zero is not allowed
# raise from: exception chaining (preserving the cause)
def load_config(path):
try:
with open(path) as f:
return f.read()
except FileNotFoundError as e:
raise RuntimeError(f"Failed to load config file: {path}") from e
try:
load_config('config.json')
except RuntimeError as e:
print(e) # Failed to load config file: config.json
print(e.__cause__) # The original FileNotFoundError
# Simple custom exception class
class ValidationError(Exception):
pass
class AgeError(ValidationError):
pass
def validate_age(age):
if not isinstance(age, int):
raise TypeError(f"Age must be an integer: {type(age).__name__}")
if age < 0:
raise AgeError(f"Age must be 0 or greater: {age}")
if age > 150:
raise AgeError(f"Age is too large: {age}")
return age
try:
validate_age(-5)
except AgeError as e:
print(f"Age error: {e}")
# Custom exception with additional details
class HttpError(Exception):
def __init__(self, message, status_code):
super().__init__(message)
self.status_code = status_code
def __str__(self):
return f"[{self.status_code}] {super().__str__()}"
def fetch(url):
if not url.startswith('https://'):
raise HttpError("Only HTTPS is allowed", 400)
try:
fetch('http://example.com')
except HttpError as e:
print(e) # [400] Only HTTPS is allowed
print(e.status_code) # 400
Notes
Using custom exception classes lets you represent different kinds of errors in code. For example, a web application might use HttpError while a validation routine uses ValidationError, allowing the caller to catch only the exceptions it needs to handle.
The raise NewException from OldException syntax is called exception chaining. It converts a low-level exception into a higher-level one while preserving the original cause in the __cause__ attribute. If you use raise without from, Python automatically stores the original exception in __context__, but using from explicitly is recommended when the conversion is intentional.
If you find any errors or copyright issues, please contact us.