Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can one declare an abstract exception in Python?

I would like to declare a hierarchy of user-defined exceptions in Python. However, I would like my top-level user-defined class (TransactionException) to be abstract. That is, I intend TransactionException to specify methods that its subclasses are required to define. However, TransactionException should never be instantiated or raised.

I have the following code:

from abc import ABCMeta, abstractmethod

class TransactionException(Exception):
    __metaclass__ = ABCMeta

    @abstractmethod
    def displayErrorMessage(self):
        pass

However, the above code allows me to instantiate TransactionException...

a = TransactionException()

In this case a is meaningless, and should instead draw an exception. The following code removes the fact that TransactionException is a subclass of Exception...

from abc import ABCMeta, abstractmethod

class TransactionException():
    __metaclass__ = ABCMeta

    @abstractmethod
    def displayErrorMessage(self):
        pass

This code properly prohibits instantiation but now I cannot raise a subclass of TransactionException because it's not an Exception any longer.

Can one define an abstract exception in Python? If so, how? If not, why not?

NOTE: I'm using Python 2.7, but will happily accept an answer for Python 2.x or Python 3.x.

like image 922
Matthew Ross Avatar asked Nov 20 '13 21:11

Matthew Ross


1 Answers

There's a great answer on this topic by Alex Martelli here. In essence, it comes down how the object initializers (__init__) of the various base classes (object, list, and, I presume, Exception) behave when abstract methods are present.

When an abstract class inherits from object (which is the default, if no other base class is given), it's __init__ method is set to that of object's, which performs the heavy-lifting in checking if all abstract methods have been implemented.

If the abstract class inherits from a different base class, it will get that class' __init__ method. Other classes, such as list and Exception, it seems, do not check for abstract method implementation, which is why instantiating them is allowed.

The other answer provides a suggested workaround for this. Of course, another option that you have is simply to accept that the abstract class will be instantiable, and try to discourage it.

like image 152
voithos Avatar answered Sep 29 '22 04:09

voithos