[Python-Dev] Avoid formatting an error message on attribute error
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