classification
Title: Better explain "TypeError: 'tuple' object is not callable"
Type: enhancement Stage: resolved
Components: Interpreter Core Versions: Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: docs@python, eric.araujo, ezio.melotti, gvanrossum, o11c, rhettinger, serhiy.storchaka, steven.daprano, storymode7, terry.reedy
Priority: normal Keywords: easy, patch

Created on 2012-07-04 05:28 by o11c, last changed 2019-08-12 03:38 by terry.reedy. This issue is now closed.

Files
File name Uploaded Description Edit
compile-warnings.diff serhiy.storchaka, 2018-03-21 13:41
Pull Requests
URL Status Linked Edit
PR 11757 merged serhiy.storchaka, 2019-02-04 19:12
PR 11757 merged serhiy.storchaka, 2019-02-04 19:12
PR 11932 merged serhiy.storchaka, 2019-02-19 11:08
PR 11935 closed miss-islington, 2019-02-19 11:49
PR 11934 open serhiy.storchaka, 2019-02-19 11:50
Messages (16)
msg164637 - (view) Author: Ben Longbons (o11c) * Date: 2012-07-04 05:28
I frequently construct lists of tuples, such as:
[
  (1, 2, 3) # oops, missing comma!
  (4, 5, 6)
]

It would be nice if the error message gave a hint on what was *actually* wrong.

Although I always use homogeneous containers, the type that's not callable could be something other than 'tuple'.

You could possibly cut down on false positives (at the risk of false negatives) by checking that the not-callable object is newly constructed.

A better way to cut down on false positives would be to check that a list, tuple, or set is being constructed from a literal, but this might be more complex.
msg164711 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2012-07-06 01:58
I think this suggested enhancement is unreasonable and of limited usefulness, and even if it were useful, too specialised to bother with.

The obvious message is badly misleading. When I read this:

TypeError: 'tuple' object is not callable, a comma may be missing

I look inside the tuple for a missing comma. But that's not the problem, and the error message sends me on a wild goose chase wondering how on earth a missing comma causes Python to try calling my tuple. I've been programming in Python for 15+ years and it mislead me -- what do you think it will do to beginners?

The problem is that the tuple is inside a list, and the LIST is missing a comma.

What about this example?

result = function(
    "the error has nothing to do with tuples"  # oops missed a comma
    (2, 3, 4),
    None
    )

Should the error message say something like:

TypeError: 'str' object is not callable, perhaps it is embedded in a list, tuple, 
function call or some other place you need a comma, and you forgot one 
or more commas?

I don't think so. Besides, most of the time when you get this TypeError, it will be because you genuinely tried to call what you thought was a function but wasn't, and the hint is pointless.

You tried to call a tuple as if it were a function. The reason for that is that you left out a comma in a list, but there are many other reasons that could happen, and "I frequently forget to add commas to lists" is a far too-specialised failure mode to single it out in the error message.

It is unreasonable to expect Python to debug your code for you. It tells you what you did wrong -- you called a tuple as a function -- and it is up to you to determine why.
msg164716 - (view) Author: Ben Longbons (o11c) * Date: 2012-07-06 04:46
This kind of "debug your code" is the kind of thing I've gotten used to from the Clang C/C++ compiler. Granted, compiled languages have an advantage here, but enough residual information remains for the interpreter at runtime.

And I am in no way suggesting that *every* attempt to call a non-function have the extra information.

For the cases where the error message is given, something like:
TypeError: 'tuple' object is not callable (missing preceding comma?)

The case of a homogenous container is the most important case.

I've offered two different ways to figure out whether it's a typo or an attempt to call an object that you honestly think is callable:
1. Is the called object a newly-constructed (refcount=1) tuple literal? (Also works for list, set, and dictionary literals; probably wouldn't work for string literals due to interning)
2. Does the false call occur within a container literal or function call?

I'm not intimately familiar with python bytecode or interpreter, but I'm sure anyone who is could extract this information.
msg164741 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-07-06 17:36
A FAQ entry could be added to explain this error, like we already do for the UnboundLocalError: http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
msg164774 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2012-07-07 01:44
Stephen is right; this sort of guess-the-bug heuristic is out of scope for the CPython interpreter. I believe you grossly under estimate the difficulty of such a this. Consider that idea rejected.

What *is* disconcerting is the exact form of the error message for this particular code pattern:

Traceback (most recent call last):
  File "<pyshell#0>", line 3, in <module>
    (4, 5, 6)
TypeError: 'tuple' object is not callable

Uh... There was no attempt to call the tuple (4,5,6), which was misinterpreted as a () call operator with 3 args. What might be a reasonable request is to print a size-limited representation of the object that is not callable but was attempted to be called. Truncated representations would be generally useful for traceback messages. I believe we already have them for unittest error messages.

A useful document for someone (or some people) to write would be 'How to interpret exception messages'. That could start with a catalog of messages and possible causes. 'type' would be used to stand for any specific type.

The section on TypeErrors would have an heading
  'type' object is not callable
followed by an explanation
  There are two general reasons for this message. The first is that you intentionally write "expression(args)" with the intent that expression evaluate to a callable, but it does not. The second is that you accidentally omit a comma in a sequence and write "expression (tuple_members)". Note that the error is triggered by the "(args)" call operator and its line is the one printed. So if "expression" is on the preceeding line, it will not appear in the traceback. This can happen with either type of error.

In the meanwhile, the above is a start for a faq entry.
msg314197 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-21 13:40
It is possible to make the compiler producing warnings for such kind of errors. The following sample patch does this. I'm not sure it is worth to do.
msg314218 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2018-03-21 18:21
Reviewing Serhiy's patch, I changed my mind from 6 years ago (msg164774).  I may have over-estimated the difficulty; in any case the code patch is written.  (Tests are still needed.)  And the code is rather straightforward and readable.

Beyond that, I see the patch as detecting a SyntaxError during compilation, as explained below, with the hint being frosting on top of that.  (It is not an 'Error' as the grammar is now, but it is an error as we might like it to be, hence Serhiy used SyntaxWarning instead.)

In addition, we now have the 'print' precedent of 'print'.
  >>> print 1
  SyntaxError: Missing parentheses in call to 'print'. Did you mean print(1)?
I don't remember when this was added, but I don't see any mention above.

And it seems from other discussions, like the recent python-ideas thread about possibly deprecating 'string' 'joining', that several people have much more of a problem with missing commas than some of us do.

If it were possible, we would like the 'call' production to be
  call ::=  callable "(" [argument_list [","] | comprehension] ")"
but 'callable' is not syntactically definable.  What is syntactically definable and what Serhiy's patch implements is
 possible_callable  ::= primary - <obvious exclusions>
 call  ::= possible_callable ...

As it happens, our grammar metasyntax does not (I believe) include set difference, and I suspect that implementing 'possible_callable' by set addition would result in something that is not LL(1) and possibly ambiguous.  Even if 'possible_callable' could be defined within the LL(1) constraint, I suspect it would be messy, and special-casing would still be needed for the special-case message.

Ditto for 'possibly_subscriptable'.

I have 3 questions:
1. Why 'chech' instead of 'check'?
2. Will chech_index catch "[1,2] [3,4]"? (I am guessing that is the intent.)
3. Does Syntax Warning stop compilation, or at least execution, as at a >>> prompt?

Aside from that, I would be inclined to mark this for 'Interpreter Core' and seriously consider it.
msg314220 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-21 18:59
Actually the precedence was a warning for an assert like:

    assert(x % 2 == 0, "x is odd")

Currently it is the only syntax warning produced by the compiler.

> 1. Why 'chech' instead of 'check'?

Just a typo replicated with a copy-paste.

> 2. Will chech_index catch "[1,2] [3,4]"? (I am guessing that is the intent.)

Yes, it is. It could be extended to catch also "['foo','bar'] ['baz']".

> 3. Does Syntax Warning stop compilation, or at least execution, as at a >>> prompt?

No, it is just a warning unless you run Python with -Werror.

This patch was inspired by usability improvements in GCC 8 [1]. I haven't created a pull request because I have doubts about that this should be in the compiler rather of a third-party linter. But if several other core developers will support this idea I'll continue working in this direction.

[1] https://developers.redhat.com/blog/2018/03/15/gcc-8-usability-improvements/
msg334306 - (view) Author: Mayank Singhal (storymode7) * Date: 2019-01-24 17:06
Hey, if nobody is working on this can I go for it?
msg334324 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2019-01-24 20:45
I am not sure what you could do at the moment.  We have not yet settled whether this is a documentation or interpreter core issue.

I posted "Add more SyntaxWarnings?" to pydev to get more comments on Serhiy's patch, especially for other core developers.  Depending on what people think, that *might* result in someone converting the diff (with the typo corrected) into a PR.

I already posted here a prototype doc entry for TypeError messages.  I decided that I should take time out from IDLE to post my idea for a separate error message doc.  I will include a fleshed-out TypeError entry (with code example) as an example entry.
msg335668 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-02-16 06:12
New changeset 62e4481238b82f111ffb1104a4b97099dd83ae2b by Serhiy Storchaka in branch 'master':
bpo-15248: Emit a compiler warning when missed a comma before tuple or list. (GH-11757)
https://github.com/python/cpython/commit/62e4481238b82f111ffb1104a4b97099dd83ae2b
msg335934 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-02-19 11:49
New changeset 8e79e6e56f516385ccb761e407dfff3a39253180 by Serhiy Storchaka in branch 'master':
Fix syntax warnings in tests introduced in bpo-15248. (GH-11932)
https://github.com/python/cpython/commit/8e79e6e56f516385ccb761e407dfff3a39253180
msg349375 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2019-08-11 06:01
This isn't interacting well with IDLE.

====================================================
--- Works fine at the regular interactive prompt ---

$ python3.8
Python 3.8.0b3 (v3.8.0b3:4336222407, Jul 29 2019, 09:46:03)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> data = [
...          (1, 2, 3) # oops, missing comma!
...          (4, 5, 6)
...      ]
<stdin>:2: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>


====================================================
--- Behaves differently in the IDLE Shell        ---

Python 3.8.0b3 (v3.8.0b3:4336222407, Jul 29 2019, 09:46:03) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license()" for more information.
>>> data = [
         (1, 2, 3) # oops, missing comma!
         (4, 5, 6)
     ]
SyntaxError: 'tuple' object is not callable; perhaps you missed a comma?
msg349380 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-08-11 08:17
I think it would be better to open a separate issue for IDLE.
msg349395 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-08-11 16:26
This is not related to this particular warning, but to how IDLE handles SyntaxWarning. See issue34857.
msg349432 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2019-08-12 03:38
IDLE's Shell has treated SyntaxWarnings as errors since 2001.  I don't know if any other IDE's do the same.  Raymond's example did not concern me, as I think not calling known non-callables is preferable.

But not executing literal-with-is code, such as "a = 1; a is 1" and "0 is ''" is wrong.  See msg349431 of #34857 for more discussion of these cases.
History
Date User Action Args
2019-08-12 03:38:14terry.reedysetmessages: + msg349432
2019-08-11 16:26:06serhiy.storchakasetstatus: open -> closed

messages: + msg349395
components: + Interpreter Core, - IDLE
assignee: terry.reedy ->
2019-08-11 08:17:31serhiy.storchakasetmessages: + msg349380
2019-08-11 06:01:19rhettingersetstatus: closed -> open

nosy: + rhettinger
messages: + msg349375

assignee: docs@python -> terry.reedy
components: + IDLE, - Documentation
2019-02-19 11:50:30serhiy.storchakasetpull_requests: + pull_request11960
2019-02-19 11:49:21miss-islingtonsetpull_requests: + pull_request11959
2019-02-19 11:49:13serhiy.storchakasetmessages: + msg335934
2019-02-19 11:08:26serhiy.storchakasetpull_requests: + pull_request11957
2019-02-16 06:13:36serhiy.storchakasetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2019-02-16 06:12:24serhiy.storchakasetmessages: + msg335668
2019-02-04 19:12:40serhiy.storchakasetstage: needs patch -> patch review
pull_requests: + pull_request11703
2019-02-04 19:12:23serhiy.storchakasetstage: needs patch -> needs patch
pull_requests: + pull_request11702
2019-01-24 22:24:19gvanrossumsetnosy: + gvanrossum
2019-01-24 20:45:11terry.reedysetmessages: + msg334324
2019-01-24 17:06:24storymode7setnosy: + storymode7
messages: + msg334306
2018-03-21 18:59:34serhiy.storchakasetmessages: + msg314220
2018-03-21 18:21:20terry.reedysetmessages: + msg314218
versions: + Python 3.8, - Python 2.7, Python 3.3, Python 3.4
2018-03-21 13:41:21serhiy.storchakasetfiles: + compile-warnings.diff
keywords: + patch
2018-03-21 13:40:52serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg314197
2013-08-17 14:13:12ezio.melottisetversions: + Python 2.7, Python 3.3
nosy: + docs@python

assignee: docs@python
components: + Documentation
keywords: + easy
2012-07-07 01:45:58terry.reedysettitle: In "TypeError: 'tuple' object is not callable", explain that a comma may be missing -> Better explain "TypeError: 'tuple' object is not callable"
stage: needs patch
versions: + Python 3.4
2012-07-07 01:44:59terry.reedysetnosy: + terry.reedy
messages: + msg164774
2012-07-06 17:36:39ezio.melottisetnosy: + ezio.melotti
messages: + msg164741
2012-07-06 04:46:15o11csetmessages: + msg164716
2012-07-06 01:58:42steven.dapranosetnosy: + steven.daprano
messages: + msg164711
2012-07-05 18:43:29eric.araujosetnosy: + eric.araujo

title: In "TypeError: 'tuple' object is not callable", suggest a comma. -> In "TypeError: 'tuple' object is not callable", explain that a comma may be missing
2012-07-04 05:28:42o11ccreate