-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent SyntaxError for print #78194
Comments
Python 3.8.0a0 (heads/master-dirty:0cdf5f4289, Jul 1 2018, 02:30:31)
[Clang 9.1.0 (clang-902.0.39.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print "hi"
File "<stdin>", line 1
print "hi"
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("hi")?
>>> def add(a,b):
... return a + b
...
>>> print add(3,5)
File "<stdin>", line 1
print add(3,5)
^
SyntaxError: invalid syntax IMHO, an error message should be 'SyntaxError: Missing parentheses in call to 'print'. Did you mean print(add(3,5))?' but it is not. |
Related issue that introduced the error message if you would like to take a look at the implementation : https://bugs.python.org/issue30597 Thanks |
Thanks, I have interest with this issue :) Thanks! |
I'm interested to solve this issue |
I took an initial stab at this and there is a comment where if there is an open paren then to use the normal error message. Additional context on the issue which lists false positive cases where the change was introduced https://bugs.python.org/issue21669. I removed the check where the left paren count is not -1 in case of a function call and it seems to work. Of course, there are cases to handle as mentioned in the linked issue and I tried some of the cases like "foo".toupper().tolower() and the results as below : Patch : diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index bb50c1c..7e616cf 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2966,10 +2966,7 @@ _report_missing_parentheses(PySyntaxErrorObject *self)
if (left_paren_index < -1) {
return -1;
}
- if (left_paren_index != -1) {
- /* Use default error message for any line with an opening paren */
- return 0;
- }
+
/* Handle the simple statement case */
legacy_check_result = _check_for_legacy_statements(self, 0);
if (legacy_check_result < 0) { Cases : ➜ cpython git:(master) ✗ cat foo_print.py print Foo().header(a=foo(1)) ➜ cpython git:(master) ✗ cat foo_print.py Linked cases in the patch : ➜ cpython git:(master) ✗ cat foo_print.py Would like to link to https://hackmd.io/s/ByMHBMjFe#08-Debugging-Python-Objects . As a beginner the tutorial was helpful and I had to set a break point on Objects/exceptions.c:1323 where SyntaxError_init is called and then execute line by line where the current code returns the left_paren_index which you can set as Thanks |
Thanks, my easy patch is worked by pre-checking left paren index. but some edge case which I don't expect should be considered. if (left_paren_index != -1) {
- /* Use default error message for any line with an opening paren */
- return 0;
+ int found_white_space = 0;
+ int found_other_char = 0;
+ Py_ssize_t pos = 0;
+ while(pos != left_paren_index) {
+ int kind = PyUnicode_KIND(self->text);
+ void *data = PyUnicode_DATA(self->text);
+ Py_UCS4 ch = PyUnicode_READ(kind, data, pos);
+ if (Py_UNICODE_ISSPACE(ch)) {
+ found_white_space = 1;
+ }
+ if (!Py_UNICODE_ISSPACE(ch) && found_white_space == 1) {
+ found_other_char = 1;
+ }
+ pos++;
+ }
+
+ if (found_other_char == 0) {
+ return 0;
+ }
} Type "help", "copyright", "credits" or "license" for more information.
>>> print (foo.)
File "<stdin>", line 1
print (foo.)
^
SyntaxError: invalid syntax
>>> print "a".toupper().tolower()
File "<stdin>", line 1
print "a".toupper().tolower()
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("a".toupper().tolower())? SyntaxError: Missing parentheses in call to 'print'. Did you mean print(Foo().header(a=foo(1)))? |
>>> class Foo:
... pass
...
>>> print Foo().header(a=foo(1))
File "<stdin>", line 1
print Foo().header(a=foo(1))
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(Foo().header(a=foo(1)))? |
And here's my work in progress patch. |
@corona10 You might want to discuss this at https://mail.python.org/pipermail/python-ideas/ so that you get some initial feedback on the work and it's acceptance to the core. Thanks |
Eric, Nick, Serhiy: this issue proposes to extend the print message patch of bpo-30597 to cover more cases. On the face of it, this seems sensible, but I have no read the original discussion or the current and proposed patches. |
See also bpo-32685. |
Still the same in 3.10: Python 3.10.0a5+ (heads/master:bf2e7e55d7, Feb 11 2021, 23:09:25) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print 3
File "<stdin>", line 1
print 3
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(3)?
>>> def f(x): return x
...
>>> print f(3)
File "<stdin>", line 1
print f(3)
^
SyntaxError: invalid syntax |
Would it be too much if add a Python 2 rule for print statement in grammar to produce better error message? invalid_print_stmt: |
Please, go ahead. I think it makes sense and with our latest change in the parser, such new error message will have no impact on performance whatsoever. Please, at me as a reviewer :) |
Aren't we overthinking this? Python 2 is a dead language. It has reached end of life more than a year ago (and was scheduled to do so in 2015). Why are we still trying to accomodate something that stopped being relevant a long time ago? |
It's still one of the most common beginner mistakes, personally I think the trade-off in complexity at least for the grammar level fix is worth it here. |
'Consistency' is in the eye of the beholder in that it is relative to some ideal. 'Inconsistent' has too much baggage as bad'. I would prefer to call the current rule 'restricted' or 'limited' and judge any expansion on its own merits. The arguments to print can take an unbounded amount of space. So a general message "Did you mean print(<full argument list>)?" could also be indefinitely long. I don't think this is a good idea. Of course, the same applies to a single literal, especially multiline string literals. But at least the latter are currently clipped to only the first line in the message. >>> print '''first line
second line'''
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('''first line)? (The above would be better with trailing ... .) This abbreviation would be harder with multiple arguments. The special message is for beginners. They might print a literal or name without ()s more frequently. I not sure that they need the reminder with every mistake. |
I agree with Terry’s point about printing long expressions in the error msg. Perhaps just the preamble would be useful though: SyntaxError: Missing parentheses in call to 'print'. Instead of just SyntaxError: invalid syntax. |
Do you have any data to back this up? I really think it's overblown. On the other hand, if it really _is_ so, how about changing the language? It wouldn't be the first thing that was changed for Py3, and then changed back once people realized the old way was better. It seems to me totally backwards to have a construct in the grammar, only to report it as an error. "I understand you, but you still have to use _this_ way to write what you want." I really think Python shouldn't be that kind of language. |
Let's step back a bit and focus on the issue at hand. The problem is the following:
Python 3.9.1 (default, Dec 14 2020, 11:49:16)
[Clang 12.0.0 (clang-1200.0.32.27)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print x
File "<stdin>", line 1
print x
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(x)? This is achieved by inspecting the syntax error and checking some conditions, which I personally find it uglier than a resilient grammar rule.
|
+1 to the idea of adding something to the grammar, and have a simple error message: SyntaxError: Missing parentheses in call to 'print'. in *all* cases, including the first one that prompted this bug report. I write that even though I have created a third-party package based on the idea that beginners (and sometimes others...) might benefit from a more detailed error message (which is taken care of already by friendly-traceback). |
This case has changed recently, and not for the better: >>> print f(3)
File "<stdin>", line 1
print f(3)
^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma? |
Reopening as a release blocker. It appears that this new rule is far too eager, and matches a much wider range of inputs than intended. Here is a case where it changes an IndentationError into a SyntaxError: $ cat bug.py
print()
boom On 3.9 (correct): $ ./python.exe --version
Python 3.9.6+
$ ./python.exe bug.py
File "/Users/brandtbucher/Desktop/GitHub/cpython/bug.py", line 2
boom
IndentationError: unexpected indent On 3.10 (incorrect): $ ./python.exe --version
Python 3.10.0b4+
$ ./python.exe bug.py
File "/Users/brandtbucher/Desktop/GitHub/cpython/bug.py", line 1
print()
^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)? On 3.11 (incorrect): $ ./python.exe --version
Python 3.11.0a0
$ ./python.exe bug.py
File "/Users/brandtbucher/Desktop/GitHub/cpython/bug.py", line 1
print()
^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)? I recommend that this either be fixed or reverted before the RC. |
Is not about the eagerness, the problem is that it matches *first*, the parser never gets to the indentation error in the second phase. For example, with: print(3) $ 34 ❯ ./python bug.py The problem is that is matching the (3) as print + a number between parentheses. We just need to disallow to continue matching on the right |
Python 3.10.0rc1 ... >>> print hello world!
File "<stdin>", line 1
print hello world!
^^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma? The hint given is not exactly helpful ... (This example was in a discussion on Twitter https://twitter.com/cfbolz/status/1425036431974715400 about a previous handling of this invalid syntax case where it was mentioned that pypy verifies that the suggestion it makes actually yields syntactically valid code.) |
If we change the priority of the error messages, which is unclear if is easily possible, the error will suggest that print hello should be parenthesized as print (hello) Which if corrected will leave the "world" part out as a call followed to a name, and here the comma suggestion is a valid concern. I understand the willingness to have a better error here, but I am not sure what we can improve here. |
I think that this was properly closed after the last fix. There are multiple issues at play:
As long as we only had one special case hint, which depended on the semantic knowledge that 'print' is almost certainly meant to mean print with the builtin function with a known call syntax, it was fairly easy to get the hint right, and in 3.11 we still have >>> print """jsfl sf
... sjflsfj l
... sjflsjf
... sjfs fj
... sjlsfjlsjg
... """
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)? But we now have more hints, and "print Hello world!" is syntactically the same as "a b c!", which gives the same error message. Even if the first identifier is recognized as a function, and parenthesis are added, the result would be syntactically identical to "print(b c!)". At this point, it is syntactically ambiguous whether the fixed argument should be a string "'b c!'" or comma list "b, c". Both are possible for print, but not all functions. The 'correct' fix on only 'obvious' when we add knowledge of the semantics 'Hello, 'world', and '!' and the history of their concatenation, 'Hello world!' (but sometimes without '!' or capitalization, or with <name> replacing 'world'), in computing, and especially in the teaching of beginners in a particular language. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: