Are python Exceptions as class attributes a bad thing?
Question: I find myself often wanting to structure my exception classes like this:

    
    
    # legends.py
    class Error(Exception): pass
    
    class Rick(object):
        class Error(Error): pass
        class GaveYouUp(Error): pass
        class LetYouDown(Error): pass
    
    class Michael(object):
        class Error(Error): pass
        class BlamedItOnTheSunshine(Error): pass
        class BlamedItOnTheMoonlight(Error): pass
    

I have only seen this pattern used in Django (`DoesNotExist`) and it makes so
much sense. Is there anything I'm missing, why most people seem to favor top-
level Exceptions?

**edit** I would use these classes for versatile granularity, e.g:

    
    
    import legends
    
    try:
        do_stuff()
    except legends.Michael.Error:
        blame_it_on_the_boogie()
    except legends.Rick.GaveYouUp:
        let_you_down()
    except legends.Error:
        pass
    except Exception as e:
        raise Hell()
    


Answer: This is the exact pattern used by Django for certain ORM-related exceptions.

The advantage is that you can have an except clause which checks against a
type accessed through an instance:

    
    
    rick = Rick()
    
    try:
       rick.roll()
    except rick.GaveYouUp:
       never()
    except rick.LetYouDown:
       never_ever()
    

This doesn't look that useful here, but if `rick` were a function parameter,
then it would potentially be rather useful.

This is also extremely useful in writing generic code which raises the
exceptions:

    
    
    GoddamStar(object):
       def sing(self,tune):
           raise self.Error()
    
    class Rick(GoddamStar):
        class Error(Error): pass
        class GaveYouUp(Error): pass
        class LetYouDown(Error): pass
    
    class Michael(GoddamStar):
        class Error(Error): pass
        class BlamedItOnTheSunshine(Error): pass
        class BlamedItOnTheMoonlight(Error): pass
    
    rick = Rick()
    
    try:
       rick.sing()
    except Rick.GaveYouUp:
       never()
    except Michael.Error:
       never_ever()
    

Django's exceptions generally all derive from global base classes, so that you
can also have a catch-all clause which still switches on a type of exception,
in case your `rick` is of an unknown (or otherwise unprovided for) class.

The reason why this isn't much more common is that (a) it doesn't work in
early-bound languages, which attract most of the book writers (b) it's
moderately rare that this is useful to the user, and so application writers
likely figure they aren't going to need it.

