EpicAdv
EpicAdv

Reputation: 1212

How is base Exception getting initialized?

I'm confused by how the following exception in Python 3 gets initialized.

class MyException( Exception ):

    def __init__(self,msg,foo):
        self.foo = foo

raise MyException('this is msg',123)

In Python 3, this outputs:

Traceback (most recent call last):
  File "exceptionTest.py", line 7, in <module>
    raise MyException('this is msg',123)
__main__.MyException: ('this is msg', 123)

How are the arguments getting initialized? I'm surprised that the trackback shows the args since I'm not calling the super class initializer.

In Python 2, I get the following output, which makes more sense to me since the args aren't included in the traceback.

Traceback (most recent call last):
  File "exceptionTest.py", line 7, in <module>
    raise MyException('this is msg',123)
__main__.MyException

Upvotes: 0

Views: 41

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122352

The Python BaseException class is special in that it has a __new__ method that is put there specifically to handle this common case of errors.

So no, BaseException.__init__ is not being called, but BaseException.__new__ is. You can override __new__ and ignore the arguments passed in to suppress the setting of self.args:

>>> class MyException(Exception):
...     def __new__(cls, *args, **kw):
...         return super().__new__(cls)  # ignoring arguments
...     def __init__(self,msg,foo):
...         self.foo = foo
...
>>> MyException('this is msg', 123)  # no need to raise to see the result
MyException()

This addition is specific to Python 3 and is not present in Python 2. See issue #1692335 for the motivations and details.

Upvotes: 3

Related Questions