classification
Title: SyntaxError: no binding for nonlocal doesn't contain a useful traceback
Type: Stage: resolved
Components: Interpreter Core Versions: Python 3.1
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: benjamin.peterson Nosy List: alex, benjamin.peterson, georg.brandl, jhylton, python-dev, r.david.murray
Priority: normal Keywords: patch

Created on 2010-10-24 19:22 by alex, last changed 2012-11-01 00:26 by python-dev. This issue is now closed.

Files
File name Uploaded Description Edit
nonlocal-traceback.patch r.david.murray, 2010-10-26 11:59 review
Messages (9)
msg119527 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2010-10-24 19:22
Given the code:

def f():
    def g():
        nonlocal a
        a = 3

Running it produces:

alex@alex-laptop:/tmp$ python3.1 test.py 
SyntaxError: no binding for nonlocal 'a' found

Compared to a different SyntaxError:

alex@alex-laptop:/tmp$ python3.1 test.py 
  File "test.py", line 1
    print a
          ^
SyntaxError: invalid syntax
msg119533 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-10-25 02:01
There are a number of such symbol resolution error messages for nonlocal that don't provide location information in symtable.c.  I'm not very experienced with hacking the C code, but a naive addition of location information based on similar calls that do provide it results in error messages that point to the "wrong" line(*).  So my guess is that the person who implemented this code just didn't get around to dealing with that localization issue.

It would appear from svn log like the person in question is Jeremy Hylton, so I'm adding him as nosy.

(*) I put wrong in quotes because it's not wrong from the point of view of the code generating the error, because that code is looking at blocks, not lines.  But it's wrong from the point of view of the user reading the message....
msg119534 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-10-25 02:09
Hmm.  Just to clarify, the commit message on the code in question specifically said that the implementation of nonlocal was not complete with that commit, and Jeremy wasn't the only one working on it.  So this detail may have simply been overlooked.
msg119536 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2010-10-25 02:35
Technically, it's because the syntax errors come from a latter part of the compiling phase when the origin of names isn't known. Fixing this would involve attaching line numbers and offsets to names somehow.
msg119537 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-10-25 02:47
I figured it was something like that, from looking at the code.

I wonder if it would be worthwhile to return the line info that is known (which I think is the start of the block containing the problematic symbol).  In a complex program that would at least get one close to the problem code.
msg119565 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-10-25 17:17
+1 for adding at least the info the symtable knows (this is already done in one of the branches in that function that raises a SyntaxError).
msg119603 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-10-26 11:59
Yes, but in that particular case the exact line referenced is involved in the error, since it that error is that the symbol is both nonlocal and an argument, and the error points to the head of the block which is the 'def' statement.

Attached is a patch that adds the available line info, and also modifies the 'nonlocal at global level' message to include the symbol name.

I think this change is a good idea because without the patch this code:

>cat temp
import foo
>cat foo.py
def f():
    def g():
        nonlocal a

gives this:

>./python temp
Traceback (most recent call last):
  File "temp", line 1, in <module>
    import foo
SyntaxError: no binding for nonlocal 'a' found

which is even more confusing that not having any traceback at all.

After the patch it will look like this:

Traceback (most recent call last):
  File "temp", line 1, in <module>
    import foo
  File "/home/rdmurray/python/py3k/foo.py", line 2
    def g():
SyntaxError: no binding for nonlocal 'a' found
msg119604 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-10-26 12:07
Ah, I hadn't noticed Benjamin assigned this to himself when I submitted that patch.  Well, maybe it will be marginally useful anyway :)
msg174387 - (view) Author: Roundup Robot (python-dev) Date: 2012-11-01 00:26
New changeset fbfaef0a9c00 by Benjamin Peterson in branch 'default':
point errors related to nonlocals and globals to the statement declaring them (closes #10189)
http://hg.python.org/cpython/rev/fbfaef0a9c00
History
Date User Action Args
2012-11-01 00:26:49python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg174387

resolution: fixed
stage: resolved
2010-10-26 12:07:53r.david.murraysetmessages: + msg119604
2010-10-26 12:00:00r.david.murraysetfiles: + nonlocal-traceback.patch
keywords: + patch
messages: + msg119603
2010-10-26 11:53:23r.david.murraysetmessages: - msg119601
2010-10-26 11:53:12r.david.murraysetmessages: + msg119601
2010-10-25 17:30:25benjamin.petersonsetassignee: benjamin.peterson
2010-10-25 17:17:15georg.brandlsetnosy: + georg.brandl
messages: + msg119565
2010-10-25 02:47:06r.david.murraysetmessages: + msg119537
2010-10-25 02:35:57benjamin.petersonsetnosy: + benjamin.peterson
messages: + msg119536
2010-10-25 02:09:18r.david.murraysetmessages: + msg119534
2010-10-25 02:01:55r.david.murraysetnosy: + jhylton, r.david.murray
messages: + msg119533
2010-10-24 19:22:06alexcreate