[Python-Dev] Avoid formatting an error message on attribute error (original) (raw)

Victor Stinner victor.stinner at gmail.com
Wed Nov 6 23:32:33 CET 2013


Hi,

I'm trying to avoid unnecessary temporary Unicode strings when possible (see issue #19512). While working on this, I saw that Python likes preparing an user friendly message to explain why getting an attribute failed. The problem is that in most cases, the caller doesn't care of the message: the exception is simply deleted. For example, hasattr() deletes immediatly the AttributeError.

It would be nice to only format the message on demand. The AttributeError would keep a reference to the type. Keeping a strong reference to the type might change the behaviour of some applications in some corner cases. (Holding a reference to the object would be worse, and the type looks to be preferred over the type to format the error message.)

Pseudo-code for modified AssertionError:

class AttributeError(Exception):
    def __init__(self, type, attr):
        self.type = type
        self.attr = attr
        self._message = None

    def __str__(self):
        if self._message is None:
            self._message = ("type object %s has no attribute %r"
                             % (self.type.__name__, self.attr))
        return self._message

AttributeError.args would be (type, attr) instead of (message,). ImportError was also modified to add a new "name "attribute".

If AttributeError cannot be modified (because of backward compatibility), would it be possible to add a new exception inheriting from AttributeError?

I have a similar project for OSError (generate the message on demand), but it's more tricky because os.strerror(errno) depends on the current locale...


Example of C code raising an AttributeError:

PyErr_Format(PyExc_AttributeError,
             "'%.50s' object has no attribute '%U'",
             tp->tp_name, name);

Example of C code ignoring the AttributeError:

value = _PyObject_GetAttrId(mod, &PyId___initializing__);
if (value == NULL)
    PyErr_Clear();
else {
    ...
}

Example of Python code ignoring the AttributeError:

try:
    get_subactions = action._get_subactions
except AttributeError:
    pass
else:
    ...

Another example in Python:

try:
    retattr = getattr(self.socket, attr)
except AttributeError:
    # the original error is not used
    raise AttributeError("%s instance has no attribute '%s'"
                         %(self.__class__.__name__, attr))

Victor



More information about the Python-Dev mailing list