Custom vs standard exceptions in Python library design: when to use which?

20 hours ago 3
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 CalibrationError

Usage:

from mylib import Detector, VideoProcessingError, CalibrationError try: detector.run("video.mp4") except VideoProcessingError: # Handle video issues except CalibrationError: # Handle calibration issues

Option 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 video
My 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.

Read Entire Article