When should I declare custom exceptions?

Creating custom exception classes…

  • gives you a declarative inventory of all the expected errors your program may produce; can make maintenance a lot easier

  • allows you to catch specific exceptions selectively, especially if you establish a useful hierarchy of them:

    class ValidationError(ValueError):
        pass
    
    class NameTooShortError(ValidationError):
        pass
    
    ...
    
    class DatabaseError(RuntimeError):
        pass
    
    class DatabaseWriteError(DatabaseError):
        pass
    
  • allows you to separate presentation from code better: The message you put into the exception is not necessarily the message the end user will see, especially if you localise your app into multiple languages. With custom classes, you can write your frontend something like this (using generic common HTML template syntax, _() is the gettext localisation function):

    {% if isinstance(e, NameTooShortError) %}
      <p>{{ _('Entered name is too short, enter at least %d characters') % e.min_length }}</p>
    {% elif isinstance(...) %}
      ...
    {% else %}
      {# fallback for unexpected exceptions #}
      <p>{{ _('An error occurred: %s') % e }}</p>
    {% endif %}
    

    Try that with just ValueError(f'Name too short: {name}')