This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author steven.daprano
Recipients cool-RR, steven.daprano
Date 2020-01-06.09:50:59
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <20200106095052.GB839@ando.pearwood.info>
In-reply-to <1578263546.29.0.437829137339.issue39212@roundup.psfhosted.org>
Content
On Sun, Jan 05, 2020 at 10:32:26PM +0000, Ram Rachum wrote:
[...]
> TypeError: __init__() takes 2 positional arguments but 3 were given        
> 
> As you can see, it's pretty simple to get this exception text, so I'm not sure why you didn't get that text. 

But I *did* get that text. I'm asking how you got the *different* text 
which you gave in your initial request.

Firstly, you stated that you got the fully-qualified exception type:

    builtins.TypeError

rather than just TypeError, which was my question. How did you get the 
fully-qualified exception class?

Secondly you quoted the error message:

    __init__() takes 1 positional argument but 2 were given

which is what I get in 3.5 using `def __init__(self)`, but in 3.8 it 
gives a different message "MyClass() takes no arguments".

I'm not worried about the error message discrepency, since that's 
irrelevant to your enhancement request, and easily explained if you were 
quoting from an older version of Python. But I don't know how you got 
the `builtins.TypeError` fully-qualified part. That is the part I'm 
asking about.

> Regarding you saying it's more annoying than useful: Especially for 
> methods such as `__init__`, it's often difficult to understand which 
> class is being instantiated, especially in a complex codebase.

I agree with you that there are occasions where this could be difficult. 
Apart from the "no source code" case, I can see that might be the case 
if the failing line is a complex expression like this:

    do_things(Spam(arg)[Eggs(None)] + Cheese(Aardvark(thingy)))

and you don't know which of Spam, Eggs, Cheese or Aardvark has failed. 
Or in an expression like this:

    lookup_class['some key'](arg)

where the source is only an indirect reference to the class you want.

But in my experience, the great bulk of calls to classes (apart from 
simple "atomic" values like int, float, str, etc) stand alone:

    obj = MyClass(arg)

and there is no difficulty in telling which class has the problem.

In my experience, I would say > 90% easy cases and < 10% tricky cases. 
(YMMV.)

So in my opinion, and I recognise that you may disagree, this is only of 
benefit in a minority of cases. For the majority of cases, it will only 
be additional noise in the message that adds nothing that wasn't already 
obvious from the source line.

And in particular, beginners are often intimidated by error messages, 
and the longer the error message, the more they are intimidated. In that 
case, `TypeError: __init__ ...` is shorter and therefore less scary than 
`builtins.TypeError: package.some_module.MyClass.__init__ ...`.

So I'm not disputing that this will be useful *sometimes*. I'm just 
trying to weigh up the cons of longer, more complex error messages 
with redundant information versus the occasional cases where the 
information is helpful.
History
Date User Action Args
2020-01-06 09:51:00steven.dapranosetrecipients: + steven.daprano, cool-RR
2020-01-06 09:51:00steven.dapranolinkissue39212 messages
2020-01-06 09:50:59steven.dapranocreate