[Python-Dev] Avoid formatting an error message on attribute error
Steven D'Aprano
steve at pearwood.info
Thu Nov 7 01:20:31 CET 2013
On Wed, Nov 06, 2013 at 11:32:33PM +0100, Victor Stinner wrote:
> 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.
My initial instinct here was to say that sounded like premature
optimization, but to my surprise the overhead of generating the error
message is actually significant -- at least from pure Python 3.3 code.
That is, the time it takes to generate the message:
"'%s' object has no attribute %r" % (obj.__class__.__name__, attrname)
is about the same as the time to raise and catch an exception:
try:
raise AttributeError
except AttributeError:
pass
(measured with timeit).
Given that, I wonder whether it would be worth coming up with a more
general solution to the question of lazily generating error messages
rather than changing AttributeError specifically. Just thinking aloud --
perhaps this should go to python-ideas? -- maybe something like this:
class _LazyMsg:
def __init__(self, template, obj, attrname):
self.template = template
self.typename = type(obj).__name__
self.attrname = attrname
def __str__(self):
return self.template % (self.typename, self.attrname)
Then:
py> err = AttributeError(
... _LazyMsg("'%s' object has no attribute '%s'", None, "spam"))
py> raise err
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'spam'
Giving the same effect from C code, I leave as an exercise for the
reader :-)
> It would be nice to only format the message on demand. The
> AttributeError would keep a reference to the type.
Since only the type name is used, why keep a reference to the type
instead of just type.__name__?
> AttributeError.args would be (type, attr) instead of (message,).
> ImportError was also modified to add a new "name "attribute".
I don't like changing the signature of AttributeError. I've got code
that raises AttributeError explicitly.
--
Steven
More information about the Python-Dev
mailing list