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.

classification
Title: TypeError message became less helpful in Python 2.7
Type: behavior Stage:
Components: Interpreter Core Versions: Python 2.7
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: BreamoreBoy, benjamin.peterson, eric.araujo, gjb1002, ncoghlan, terry.reedy
Priority: normal Keywords:

Created on 2010-09-24 19:44 by gjb1002, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (10)
msg117327 - (view) Author: Geoffrey Bache (gjb1002) Date: 2010-09-24 19:44
Consider the following code:

### keywords.py

def f(**kw):
    print arg, kw

f("hello", keyword=True)

and compare the behaviour in Python 2.6 and Python 2.7:

$ python keywords.py 
Traceback (most recent call last):
  File "keywords.py", line 5, in <module>
    f("hello", keyword=True)
TypeError: f() takes exactly 0 non-keyword arguments (1 given)

$ python2.7 keywords.py
Traceback (most recent call last):
  File "keywords.py", line 5, in <module>
    f("hello", keyword=True)
TypeError: f() takes exactly 0 arguments (2 given)

The error message from 2.6 is I would say a more accurate description of the situation.
msg117346 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2010-09-25 03:15
r85003 Thanks for the report.
msg117347 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2010-09-25 03:26
Reverted, however. Let me clarify: you think the unhelpful part is that the count includes keyword arguments? This change was intentional, actually wrt to cases like this:

    >>> def f(a):
    ...    pass
    >>> f(6, a=4, *(1, 2, 3))
    Traceback (most recent call last):
      ...
    TypeError: f() takes exactly 1 positional argument (5 given)
    >>> def f(a, *, kw):
    ...    pass
    >>> f(6, 4, kw=4)
    Traceback (most recent call last):
      ...
    TypeError: f() takes exactly 1 positional argument (3 given)
msg117354 - (view) Author: Geoffrey Bache (gjb1002) Date: 2010-09-25 10:27
I think the unhelpful part is mostly that it does not distinguish between argument types any more when the distinction is important in this context. In fact, it could be argued that what it said isn't even true:

f() takes exactly 0 arguments (2 given)

f() doesn't take exactly 0 arguments. It takes any number of arguments, so long as they are keyword arguments.

Surely you agree that the Python 2.6 error describes the problem more accurately?

As for your examples, the message in the first one has changed from

TypeError: f() takes exactly 1 non-keyword argument (4 given)

to 

TypeError: f() takes exactly 1 argument (5 given)

which is possibly a marginal improvement, although taken together I would say this isn't an improvement, especially as I think examples like my first one are more widespread (OK, I didn't even know this syntax was legal...)

Your second example is only legal syntax in Python 3, so I don't really get the point with respect to comparing Python 2.6 and Python 2.7.
msg117413 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2010-09-26 12:28
Having seen the reversion go by on the checkins list, I think there are distinctions the interpreter should be making here in order to improve the error messages, but it isn't.

Ideally, we want to be able to tell the user (without writing War and Peace as an error message):

1. How many positional parameters are expected
2. How many positional parameters were supplied as positional arguments
3. How many positional parameters were supplied as keyword arguments

For example:

Def: f(**kw)
Call: f("hello", keyword=True)
Error: f() does not accept positional arguments (1 given)

Def: f(x, **kw)
Call: f("hello", "goodbye", keyword=True)
Error: f() accepts at most 1 positional argument (2 given)

Def: f(x, **kw)
Call: f("hello", x="goodbye", keyword=True)
Error: f() accepts at most 1 positional argument (2 given, 1 via keyword)

Basically:
1. Get rid of the "exactly"/"at most" distinction ("exactly" is wrong, since you can always provide positional arguments as keyword arguments instead)
2. Use "positional" instead of the awkward "non-keyword"
3. Append additional info when some or all of the positional arguments are provided as keywords.
msg117468 - (view) Author: Geoffrey Bache (gjb1002) Date: 2010-09-27 20:05
I agree with Nick :) 

Though I'd say fixing a regression should take priority over further enhancing the messages.
msg117820 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2010-10-01 18:09
FWIW 3.1 gives same message as 2.6. I have not installed 3.2a yet to check that.

Reporting of argument count mismatch has always been problematical, especially for methods. I almost think the message should be simplified to "Arguments passed do not match function signature." Programmers who do not immediately immediately see the problem (because they know the signature but made an inadvertent mistake) will have to check the signature anyway.

The alternative should be a clearer and more complete report than currently, which will take more than one line.
msg227784 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2014-09-28 23:54
3.4.1 and 3.5.0a0 give the same message as 2.6.  I don't have 2.7 to see what it currently does.
msg227786 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-09-29 02:20
Still TypeError: f() takes exactly 0 arguments (2 given).  I consider the 2.6/3.x message better (more accurate).  But at this point, I could be persuaded to leave 2.7 alone and close this.
msg227787 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2014-09-29 02:57
Yes, the argument error messages for 2.x are all not very good. Note this issue was fixed once and for all in Python 3:

% python3 x.py
Traceback (most recent call last):
  File "x.py", line 3, in <module>
    f("hello", keyword=True)
TypeError: f() takes 0 positional arguments but 1 was given
History
Date User Action Args
2022-04-11 14:57:06adminsetgithub: 54152
2014-09-29 02:57:24benjamin.petersonsetstatus: open -> closed
resolution: wont fix
messages: + msg227787
2014-09-29 02:20:32terry.reedysetmessages: + msg227786
2014-09-28 23:54:50BreamoreBoysetnosy: + BreamoreBoy
messages: + msg227784
2010-10-01 18:09:31terry.reedysetnosy: + terry.reedy
messages: + msg117820
2010-09-27 20:05:58gjb1002setmessages: + msg117468
2010-09-27 19:50:51eric.araujosetnosy: + eric.araujo
2010-09-26 12:28:48ncoghlansetnosy: + ncoghlan
messages: + msg117413
2010-09-25 10:27:50gjb1002setmessages: + msg117354
2010-09-25 03:26:26benjamin.petersonsetstatus: closed -> open
resolution: fixed -> (no value)
messages: + msg117347
2010-09-25 03:15:13benjamin.petersonsetstatus: open -> closed

nosy: + benjamin.peterson
messages: + msg117346

resolution: fixed
2010-09-24 19:44:17gjb1002create