ARTICLE AD BOX
Should I use custom exceptions in my library or just standard Python exceptions?
I'm building a Python library for video processing and I'm uncertain about exception handling design. Specifically, I'm confused about when custom exceptions are appropriate vs. when standard exceptions are sufficient.
Current Situation
I have a Detector class that processes videos. During processing, several things can go wrong:
Video file doesn't exist Video file exists but can't be opened (corrupted, wrong format) Video opens but frames can't be read Calibration fails (not enough detections)Option 1: Custom Exceptions
class VideoProcessingError(Exception): pass class CalibrationError(Exception): pass class Detector: def _validate_video(self, video_path): if not Path(video_path).exists(): raise VideoProcessingError(f"Video not found: {video_path}") cap = cv2.VideoCapture(str(video_path)) if not cap.isOpened(): raise VideoProcessingError(f"Cannot open video: {video_path}") ret, frame = cap.read() if not ret: raise VideoProcessingError(f"Cannot read frames: {video_path}") def run(self, video_path): self._validate_video(video_path) # Raises VideoProcessingError self._calibrate(video_path) # Raises CalibrationErrorUsage:
from mylib import Detector, VideoProcessingError, CalibrationError try: detector.run("video.mp4") except VideoProcessingError: # Handle video issues except CalibrationError: # Handle calibration issuesOption 2: Standard Exceptions
class Detector: def _validate_video(self, video_path): if not Path(video_path).exists(): raise FileNotFoundError(f"Video not found: {video_path}") cap = cv2.VideoCapture(str(video_path)) if not cap.isOpened(): raise ValueError(f"Cannot open video: {video_path}") ret, frame = cap.read() if not ret: raise ValueError(f"Cannot read frames: {video_path}")Usage:
from mylib import Detector try: detector.run("video.mp4") except FileNotFoundError: # Handle missing file except ValueError: # Handle invalid videoMy Concerns
Custom exceptions seem to force users to import them: Users need to know about VideoProcessingError and CalibrationError to catch them properly. I've never used a library where I had to import all its custom error classes.
Standard exceptions are familiar: Everyone knows FileNotFoundError and ValueError. No need to read documentation about custom exception types.
But custom exceptions are more specific: VideoProcessingError is more precise than ValueError for "this specific library had a video problem."
Questions
Is forcing users to import custom exception classes considered bad API design? When should a library use custom exceptions vs. standard ones? Do most popular Python libraries (requests, numpy, pandas, etc.) use custom exceptions, and if so, do they require users to import them? If I do use custom exceptions, should they inherit from standard ones (e.g., VideoProcessingError(ValueError)) so users can catch either?What I've Tried
I initially thought I should catch custom exceptions internally and raise generic Exception to the user:
def run(self, video_path): try: self._validate_video(video_path) except VideoProcessingError as e: logger.error(f"Validation failed: {e}") raise Exception("Video validation failed.")But this loses all the specific error information and makes custom exceptions pointless.
