Python exception - how is the args attribute automatically set?
Suppose I define the following exception:
>>> class MyError(Exception):
... def __init__(self, arg1):
... pass
Then I instantiate the class to create the exception object:
>>> e = MyError('abc')
>>> e.args
('abc',)
Here, how is the attribute set args
? ( __init__
I am not doing anything.)
source to share
It is set in a method BaseException.__new__()
that can be seen here: source code
Note: in Python 2.7 it is set in a method BaseException.__init__()
, so the override makes the .args
dict always empty (not sure, pointing to the correct string): source code
source to share
args
implemented as a data descriptor with methods __get__
and __set__
.
It happens internally BaseException.__new__
as @bakatrouble mentioned. Among other things, what's going on internally BaseException.__new__
is roughly similar to the Python code below:
class BaseException:
def __new__(cls, *args):
# self = create object of type cls
self.args = args # This calls: BaseException.args.__set__(self, args)
...
return self
In Python 3.7.0 alpha 1 C code, the above Python code looks like this (check Python C code for any past or future differences):
BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
# other things omitted...
self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
# many things follow...
if (args) {
self->args = args;
Py_INCREF(args);
return (PyObject *)self;
}
# many more things follow
}
Experimenting interactively:
>>> e = Exception('aaa')
>>> e
Exception('aaa',)
>>> BaseException.args.__set__(e, ('bbb',))
>>> e
Exception('bbb',)
>>> BaseException.args.__get__(e)
('bbb',)
Hence, the magical inspiration args
that makes your eyes look up to the sky occurs BaseException.__new__
when an object BaseException
or any of its subclasses is created.
source to share