Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python exception - how does the args attribute get automatically set?

Suppose I define the following exception:

>>> class MyError(Exception):
...     def __init__(self, arg1):
...         pass

Then I instantiate the class to create an exception object:

>>> e = MyError('abc')
>>> e.args
('abc',)

Here how is the args attribute getting set? (In the __init__, I am doing nothing.)

like image 919
debashish Avatar asked Jun 28 '17 10:06

debashish


People also ask

What is args in Python exception?

An exception can have an argument, which is a value that gives additional information about the problem.

How does Python handle custom exceptions?

Creating Custom Exceptions In Python, users can define custom exceptions by creating a new class. This exception class has to be derived, either directly or indirectly, from the built-in Exception class. Most of the built-in exceptions are also derived from this class.

How do I get error messages in Python?

If you want the error class, error message, and stack trace, use sys. exc_info() . The function sys. exc_info() gives you details about the most recent exception.

How do you catch an instance of a specific exception type in Python?

Catching Specific Exceptions in PythonA try clause can have any number of except clauses to handle different exceptions, however, only one will be executed in case an exception occurs. We can use a tuple of values to specify multiple exceptions in an except clause.


1 Answers

args is implemented as a data descriptor with __get__ and __set__ methods.

This takes place inside BaseException.__new__ like @bakatrouble mentioned. Among other things, what happens inside BaseException.__new__ is roughly like 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 C code of Python 3.7.0 alpha 1, the above Python code looks like this (inspect Python's 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 of args that makes your eyes look heavenward takes place in BaseException.__new__, when an object of BaseException or any of its sub-classes is created.

like image 81
direprobs Avatar answered Oct 23 '22 04:10

direprobs