[Python-ideas] Showing qualified names when a function call fails

Nathaniel Smith njs at pobox.com
Tue Oct 25 15:17:56 EDT 2016


On Tue, Oct 25, 2016 at 6:58 AM, Chris Angelico <rosuav at gmail.com> wrote:
> On Wed, Oct 26, 2016 at 12:20 AM, Michel Desmoulin
> <desmoulinmichel at gmail.com> wrote:
>> list, set and tuple less not as good:
>>
>>     >>> tuple(foo)
>>
>>     TypeError: 'int' object is not iterable
>>
>> No raiser, no value given. It's hard to find out what's the problem is. The
>> biggest issue here is that if you have a long line with tuple() in the
>> middle, yuou need to know the problem comes from tuple.
>>
>> Another problem is that many people don't know what iterable means.
>>
>> A better error message would be:
>>
>> TypeError: tuple() only accept iterables (any object you can use a for loop
>> on). But it received '1', which is of type <int>.
>
> -1 on this one. It doesn't really add very much - "iterable" is a good
> keyword that anyone can put into a search engine. Adding the repr of
> the object that was passed is nice if it's an integer, but less so if
> you passed in some huge object.

Agreed that showing the repr in general is tricky. The length isn't
such a big deal (you need some cleverness -- don't show the repr if
it's >40 characters, say -- but that's doable if someone wants to do
the work). What I'd be a little nervous of is the time/memory cost of
computing the repr for an arbitrary object every time a TypeError is
thrown. One possible workaround for this would be to be lazy, i.e.
wait until someone actually calls str() on the exception object before
computing the repr, but the problem then is that you'd have to attach
the offending object to the TypeError, which pins it in memory longer
than it otherwise would be. Perhaps this is an acceptable trade-off --
having the offending object around is actually pretty useful for
debugging! But we probably can't just blindly start showing repr's
everywhere -- it'll need some case-by-case consideration.

A good example actually might be the int constructor -- if the object
is an unrecognized type, then it shows the type; if it's a recognized
type but the value is bad, then it shows the value:

In [3]: int([])
TypeError: int() argument must be a string, a bytes-like object or a
number, not 'list'

In [4]: int("a")
ValueError: invalid literal for int() with base 10: 'a'

> If your lines of code are so complicated that you can't pinpoint the
> cause of the TypeError, the solution is probably to break the line.

Yes, breaking the line will also work, but often difficult to do (e.g.
you might have a traceback but not an easy recipe to reproduce the
exception), and anyway, why is that a reason to punish people who
haven't learned that trick? I get that this list's default is to push
back on proposed changes, and it's a good principle in general, but
"improved error messages" are *really* cheap. The bar should be pretty
low, IMO. If someone's willing to do the work to make the error
messages friendlier, while addressing technical considerations like
the repr issue, then that's awesome, and if that means that users get
somewhat redundant information to help them debug then... cool?
Terseness per se is not a cardinal virtue :-).

-n

-- 
Nathaniel J. Smith -- https://vorpus.org


More information about the Python-ideas mailing list