Exceptions#
Utilities for extracting and handling structured exception information.
Overview#
The exceptions module provides tools to capture detailed exception information in a structured format, making it easier to:
Log exceptions with full context
Serialize exception data for APIs
Debug production issues with complete stack traces
Monitor and track errors systematically
Quick Examples#
Basic Exception Handling#
Extract exception information during error handling:
from core_mixins.exceptions import get_exception_data
try:
result = 10 / 0
except ZeroDivisionError:
exc_type, exc_message, stack_trace = get_exception_data()
print(f"Exception Type: {exc_type}") # "ZeroDivisionError"
print(f"Message: {exc_message}") # "division by zero"
print(f"Stack Depth: {len(stack_trace)}") # Number of frames
Logging with Full Context#
Capture complete error information for logging:
import logging
from core_mixins.exceptions import get_exception_data
logger = logging.getLogger(__name__)
def process_data(data):
try:
# Process data
result = data['value'] / data['divisor']
return result
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
logger.error(
f"Error processing data: {exc_type} - {exc_message}",
extra={
"exception_type": exc_type,
"exception_message": exc_message,
"stack_trace": stack_trace
}
)
raise
API Error Responses#
Return structured error information in API responses:
from flask import jsonify
from core_mixins.exceptions import get_exception_data
@app.route('/api/calculate', methods=['POST'])
def calculate():
try:
data = request.get_json()
result = perform_calculation(data)
return jsonify({"result": result})
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
return jsonify({
"error": {
"type": exc_type,
"message": exc_message,
"stack_trace": stack_trace if app.debug else None
}
}), 500
Detailed Stack Trace Analysis#
Examine each frame in the stack trace:
from core_mixins.exceptions import get_exception_data
def divide_numbers(a, b):
return a / b
def calculate():
return divide_numbers(10, 0)
try:
calculate()
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
print(f"\nException: {exc_type} - {exc_message}\n")
print("Stack Trace:")
for frame in stack_trace:
print(f" File: {frame['File']}")
print(f" Line: {frame['Line Number']} - {frame['Line']}")
print(f" Function: {frame['Function']}")
print()
# Output:
# Exception: ZeroDivisionError - division by zero
#
# Stack Trace:
# File: /path/to/script.py
# Line: 7 - return divide_numbers(10, 0)
# Function: calculate
#
# File: /path/to/script.py
# Line: 4 - return a / b
# Function: divide_numbers
Error Monitoring System#
Build an error tracking system:
from datetime import datetime
from core_mixins.exceptions import get_exception_data
import json
class ErrorTracker:
"""Track and store application errors."""
def __init__(self):
self.errors = []
def capture_exception(self, context=None):
"""Capture current exception with context."""
exc_type, exc_message, stack_trace = get_exception_data()
error_record = {
"timestamp": datetime.utcnow().isoformat(),
"type": exc_type,
"message": exc_message,
"stack_trace": stack_trace,
"context": context or {}
}
self.errors.append(error_record)
return error_record
def export_errors(self, filepath):
"""Export errors to JSON file."""
with open(filepath, 'w') as f:
json.dump(self.errors, f, indent=2)
# Usage
tracker = ErrorTracker()
try:
# Application code
process_user_data(user_id=123)
except Exception:
tracker.capture_exception(context={"user_id": 123})
raise
Return Value Structure#
The get_exception_data() function returns a tuple with three elements:
exc_type, exc_message, stack_trace = get_exception_data()
1. Exception Type (str)
The name of the exception class:
"ZeroDivisionError"
"KeyError"
"ValueError"
"FileNotFoundError"
"Unknown" # When no exception info available
2. Exception Message (str)
The exception message describing what went wrong:
"division by zero"
"'missing_key'"
"invalid literal for int() with base 10: 'abc'"
"No such file or directory: 'data.txt'"
3. Stack Trace (List[Dict])
A list of dictionaries, each representing a stack frame:
[
{
"File": "/path/to/module.py",
"Line Number": 42,
"Line": "result = calculate(value)",
"Function": "process_data"
},
{
"File": "/path/to/helpers.py",
"Line Number": 15,
"Line": "return numerator / denominator",
"Function": "calculate"
}
]
Use Cases#
Error Logging and Monitoring#
Capture detailed error information for debugging:
Log structured exception data to monitoring systems (Sentry, DataDog, etc.)
Track error patterns and frequencies
Include stack traces in error reports
API Error Handling#
Return consistent error responses:
Standardize error response format
Include stack traces in development mode
Hide sensitive information in production
Debugging and Testing#
Analyze exception context:
Examine the call stack to find error origins
Test error handling paths
Validate exception information in tests
Error Recovery#
Make informed decisions based on exception details:
try:
perform_operation()
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
# Retry for specific errors
if exc_type in ("ConnectionError", "TimeoutError"):
retry_operation()
# Fail fast for others
else:
send_alert(exc_type, exc_message, stack_trace)
raise
Best Practices#
Always Call Within Exception Handler#
get_exception_data() must be called inside an exception handler:
# ✓ Correct
try:
risky_operation()
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
# ✗ Wrong - No exception information available
exc_type, exc_message, stack_trace = get_exception_data()
Store or Log Immediately#
Exception information is only available within the except block:
# ✓ Correct - Store data immediately
try:
operation()
except Exception:
error_data = get_exception_data()
# error_data can be used later
# ✗ Wrong - Information lost after except block
try:
operation()
except Exception:
pass
error_data = get_exception_data() # Returns empty/unknown
Don’t Expose Stack Traces in Production#
Filter sensitive information before sending to clients:
import os
try:
process_request()
except Exception:
exc_type, exc_message, stack_trace = get_exception_data()
# Include stack trace only in development
response = {
"error": exc_type,
"message": exc_message
}
if os.getenv("ENV") == "development":
response["stack_trace"] = stack_trace
API Reference#
Exception handling utilities for extracting structured exception information and stack traces.
- core_mixins.exceptions.get_exception_data() Tuple[str, str, List[Dict]][source]#
To retrieve the error information and the stack trace…
Example:
try: 8/0 except ZeroDivisionError as error: type_, message, trace = get_exception_data() Exception type: ZeroDivisionError Exception message: division by zero Stack trace: ...
- Returns:
The error information in a tuple like: (exception_type, exception_message, stack_trace).