Improve error message "UnboundLocalError: local variable referenced before assignment"

Here is the code: ---[cut]----------------------------- DEBUG = [] FONT_NAMES = [] def names(): if len(DEBUG): print(len(DEBUG)) if len(FONT_NAMES): print(len(FONT_NAMES)) if len(FONT_NAMES)==0: FONT_NAMES = "query()" names() ---[cut]----------------------------- Here is the output: Traceback (most recent call last): File "globalocal.py", line 13, in <module> names() File "globalocal.py", line 8, in names if len(FONT_NAMES): UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment As you may see there is inconsistency between handling of line 6 - "if len(DEBUG):" and line 8 - "if len(FONT_NAMES):". This is very magical and hard to troubleshoot. I wonder if this message can be improved with a pointer to the concept on when global variables become local? -- anatoly t.

On Wed, 31 Oct 2012 21:57:28 +0200, anatoly techtonik <techtonik@gmail.com> wrote:
Here is the code:
---[cut]-----------------------------
DEBUG = [] FONT_NAMES = []
def names(): if len(DEBUG): print(len(DEBUG)) if len(FONT_NAMES): print(len(FONT_NAMES)) if len(FONT_NAMES)==0: FONT_NAMES = "query()"
names() ---[cut]-----------------------------
Here is the output:
Traceback (most recent call last): File "globalocal.py", line 13, in <module> names() File "globalocal.py", line 8, in names if len(FONT_NAMES): UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment
As you may see there is inconsistency between handling of line 6 - "if len(DEBUG):" and line 8 - "if len(FONT_NAMES):". This is very magical and hard to troubleshoot. I wonder if this message can be improved with a pointer to the concept on when global variables become local?
There is no inconsistency here. Only FONT_NAMES is assigned a value in the local scope. "local variable referenced before assignment" *is* a pointer to the concept of when global variables become local...perhaps there is a better wording, do you have a suggestion? --David

On 10/31/2012 4:28 PM, R. David Murray wrote:
"local variable referenced before assignment" *is* a pointer to the concept of when global variables become local...perhaps there is a better wording, do you have a suggestion?
The current wording is an exact, concise, description of the problem. Rather than tinkering with the wording, I think a more general solution might be a new HOWTO: Understanding exception messages. It could have alphabetically sorted entries for exceptions and messages that people find problematic. UnboundLocalError local variable referenced before assignment Problem: You used a local name 'x' in an expression before you assigned it a value. So the interpreter could not compute the value of the expression. Remember that assignment makes a name local unless it is declared global or nonlocal. Remedy: If you intend 'x' to refer to a glocal or nonlocal name, add the necessary global or nonlocal declaration. If you intend -- Terry Jan Reedy

On Thu, Nov 1, 2012 at 12:20 PM, Terry Reedy <tjreedy@udel.edu> wrote:
The current wording is an exact, concise, description of the problem. Rather than tinkering with the wording, I think a more general solution might be a new HOWTO: Understanding exception messages. It could have alphabetically sorted entries for exceptions and messages that people find problematic.
UnboundLocalError
local variable referenced before assignment ... Remedy: If you intend 'x' to refer to a glocal or nonlocal name, add the necessary global or nonlocal declaration. If you intend
+1. Can this be tied in with help(UnboundLocalError) perhaps? At the moment, that produces a huge screed of details that aren't particularly helpful to a novice (all its methods etc), and only a one-line explanation "Local name referenced but not bound to a value.". If that could be shortened and expanded on, it'd be a logical place to point people. "You got an error you don't understand? Go to the interactive interpreter and type help(NameOfError) - that should tell you what it is." ChrisA

On 01/11/2012 01:45, Chris Angelico wrote:
The current wording is an exact, concise, description of the problem. Rather than tinkering with the wording, I think a more general solution might be a new HOWTO: Understanding exception messages. It could have alphabetically sorted entries for exceptions and messages that people find problematic.
UnboundLocalError
local variable referenced before assignment ... Remedy: If you intend 'x' to refer to a glocal or nonlocal name, add the necessary global or nonlocal declaration. If you intend +1. Can this be tied in with help(UnboundLocalError) perhaps? At the moment, that produces a huge screed of details that aren't
On Thu, Nov 1, 2012 at 12:20 PM, Terry Reedy <tjreedy@udel.edu> wrote: particularly helpful to a novice (all its methods etc), and only a one-line explanation "Local name referenced but not bound to a value.". If that could be shortened and expanded on, it'd be a logical place to point people. "You got an error you don't understand? Go to the interactive interpreter and type help(NameOfError) - that should tell you what it is."
ChrisA An excellent idea IMO. +1 Rob Cliffe _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/rob.cliffe%40btinternet.co...

On 10/31/2012 9:20 PM, Terry Reedy wrote:
On 10/31/2012 4:28 PM, R. David Murray wrote:
"local variable referenced before assignment" *is* a pointer to the concept of when global variables become local...perhaps there is a better wording, do you have a suggestion?
The current wording is an exact, concise, description of the problem. Rather than tinkering with the wording, I think a more general solution might be a new HOWTO: Understanding exception messages. It could have alphabetically sorted entries for exceptions and messages that people find problematic.
UnboundLocalError local variable referenced before assignment
Problem: You used a local name 'x' in an expression before you assigned it a value. So the interpreter could not compute the value of the expression. Remember that assignment makes a name local unless it is declared global or nonlocal.
Remedy: If you intend 'x' to refer to a glocal or nonlocal name, add the necessary global or nonlocal declaration. If you intend <left out> 'x' to be local, rearrange your code to give it a value before you use it.
-- Terry Jan Reedy

This post would have been more appropriate on python-list than python-dev. But to answer your implied questions... On 10/31/2012 3:57 PM, anatoly techtonik wrote:
Here is the code:
---[cut]-----------------------------
DEBUG = [] FONT_NAMES = []
This line has nothing to do with the behavior of the function that follows. The error message would be the name if it were deleted.
def names(): if len(DEBUG): print(len(DEBUG)) if len(FONT_NAMES): print(len(FONT_NAMES)) if len(FONT_NAMES)==0: FONT_NAMES = "query()"
This makes FONT_NAMES a local name *everywhere* within names.
names() ---[cut]-----------------------------
Here is the output:
Traceback (most recent call last): File "globalocal.py", line 13, in <module> names() File "globalocal.py", line 8, in names if len(FONT_NAMES): UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment
As you may see there is inconsistency between handling of line 6 - "if len(DEBUG):" and line 8 - "if len(FONT_NAMES):".
No there is not.
This is very magical and hard to troubleshoot.
Names (not 'variables') within a function are deterministically classified at compile time as local, nonlocal, or global according to declarations and usage *within the function*. This classification has nothing to do with names in other namespaces and is done independently of other namespaces. The rules are described in the manuals.
I wonder if this message can be improved with a pointer to the concept on when global variables become local?
This never happens. Global names stay global (until deleted). They may be masked by a local name with the same spelling (as in your example), but that is a different issue. -- Terry Jan Reedy

On 01/11/12 06:57, anatoly techtonik wrote: [...]
UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment
As you may see there is inconsistency between handling of line 6 - "if len(DEBUG):" and line 8 - "if len(FONT_NAMES):". This is very magical and hard to troubleshoot.
I wouldn't call it an inconsistency, because the rules for deciding whether something is treated as local or global is consistently applied to all functions and variables. I would use the word "difference" instead -- there is a difference between line 6 and line 8 because there is a difference between DEBUG (global) and FONT_NAMES (local). As to whether this is "magical" behaviour, I suppose in some sense it is, but if so, it is more like a light sprinkling of pixie dust rather than full-blown dark voodoo magic.
I wonder if this message can be improved with a pointer to the concept on when global variables become local?
If you have a suggestion for an improved message, please tell us. Or raise an issue on the bug tracker. -- Steven

Am 31.10.2012 23:15, schrieb Steven D'Aprano:
On 01/11/12 06:57, anatoly techtonik wrote: [...]
UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment [...] I wonder if this message can be improved with a pointer to the concept on when global variables become local?
If you have a suggestion for an improved message, please tell us.
I'll take a shot, since I was also bitten by this when trying to learn Python. The important point is that some code earlier or later in that function does an assignment, so this location should be referenced in the error. How about: "UnboundLocalError: Local variable 'FONT_NAMES' (created on line 11) referenced before assignment." What I don't really like is the term "created". Maybe "implicitly created on line 11"? Or "implied by line 11"? Or how about "Local variable FONT_NAMES (implied by line 11) doesn't refer to an object", to avoid the multiple interpretations of the term "assignment"? =just my 2cc= Uli ************************************************************************************** Domino Laser GmbH, Fangdieckstra�e 75a, 22547 Hamburg, Deutschland Gesch�ftsf�hrer: Hans Robert Dapprich, Amtsgericht Hamburg HR B62 932 ************************************************************************************** Visit our website at http://www.dominolaser.com ************************************************************************************** Diese E-Mail einschlie�lich s�mtlicher Anh�nge ist nur f�r den Adressaten bestimmt und kann vertrauliche Informationen enthalten. Bitte benachrichtigen Sie den Absender umgehend, falls Sie nicht der beabsichtigte Empf�nger sein sollten. Die E-Mail ist in diesem Fall zu l�schen und darf weder gelesen, weitergeleitet, ver�ffentlicht oder anderweitig benutzt werden. E-Mails k�nnen durch Dritte gelesen werden und Viren sowie nichtautorisierte �nderungen enthalten. Domino Laser GmbH ist f�r diese Folgen nicht verantwortlich. **************************************************************************************

On 7 November 2012 13:57, Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> wrote:
Am 31.10.2012 23:15, schrieb Steven D'Aprano: I'll take a shot, since I was also bitten by this when trying to learn Python. The important point is that some code earlier or later in that function does an assignment, so this location should be referenced in the error.
+1
How about:
"UnboundLocalError: Local variable 'FONT_NAMES' (created on line 11) referenced before assignment."
What I don't really like is the term "created". Maybe "implicitly created on line 11"? Or "implied by line 11"? Or how about "Local variable FONT_NAMES (implied by line 11) doesn't refer to an object", to avoid the multiple interpretations of the term "assignment"?
Why not make use of the well defined words already there in the error message, but at the line number "UnboundLocalError: Local variable 'FONT_NAMES' referenced before it has been assigned to on line 11." Sam

How about:
"UnboundLocalError: Local variable 'FONT_NAMES' (created on line 11) referenced before assignment."
What I don't really like is the term "created". Maybe "implicitly created on line 11"? Or "implied by line 11"? Or how about "Local variable FONT_NAMES (implied by line 11) doesn't refer to an object", to avoid the multiple interpretations of the term "assignment"?
It's been a long (long) while since I looked at the virtual machine implementation, but my guess is that at the point where the error is detected the system won't know what line number corresponds to the assignment. There might also be multiple assignments. How would you know which one to pick? As for a better word than "created", I would use "assigned." Skip

On Wed, 07 Nov 2012 14:57:57 +0100, Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> wrote:
Am 31.10.2012 23:15, schrieb Steven D'Aprano:
On 01/11/12 06:57, anatoly techtonik wrote: [...]
UnboundLocalError: local variable 'FONT_NAMES' referenced before assignment [...] I wonder if this message can be improved with a pointer to the concept on when global variables become local?
If you have a suggestion for an improved message, please tell us.
I'll take a shot, since I was also bitten by this when trying to learn Python. The important point is that some code earlier or later in that function does an assignment, so this location should be referenced in the error.
How about:
"UnboundLocalError: Local variable 'FONT_NAMES' (created on line 11) referenced before assignment."
What I don't really like is the term "created". Maybe "implicitly created on line 11"? Or "implied by line 11"? Or how about "Local variable FONT_NAMES (implied by line 11) doesn't refer to an object", to avoid the multiple interpretations of the term "assignment"?
The problem is that when Python executes the statement that raises the error it has no idea where the assignment was done. All it knows is that the variable is local. Keeping track of the location of every assignment that makes a variable local and writing it in to the .pyc file is a very non-trivial change to how the Python bytecode compiler works, I think, and probably not worth the overhead in order to improve this error message. (And note that raising an error at compile time would change Python's semantics.) --David

On Wed, Nov 7, 2012 at 11:57 PM, Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> wrote:
How about:
"UnboundLocalError: Local variable 'FONT_NAMES' (created on line 11) referenced before assignment."
What I don't really like is the term "created". Maybe "implicitly created on line 11"? Or "implied by line 11"? Or how about "Local variable FONT_NAMES (implied by line 11) doesn't refer to an object", to avoid the multiple interpretations of the term "assignment"?
Unfortunately, we don't track the information we would need in order to emit that kind of error message. However, you did give me an idea: I believe the compiler is actually in a position to emit SyntaxWarning for functions that have a high chance of triggering UnboundLocalError when called. With output pointing to *both* problematic lines, beginners should stand a better chance of figuring out what is going on. (http://bugs.python.org/issue16429) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Dne 31.10.2012 23:15, Steven D'Aprano napsal(a):
I wonder if this message can be improved with a pointer to the concept on when global variables become local?
If you have a suggestion for an improved message, please tell us. Or raise an issue on the bug tracker.
I believe the "human problem" here is that the one tends to gloss over "local variable VARNAME", because it describes VARNAME and you already think you know what that is, so you don't stop to think about it. The following would be better in this regard, IMO: "Variable VARNAME is local in FUNCNAME, but doesn't have a value at line 123" regards m.

On 11/12/2012 7:30 AM, Jan Matějek wrote:
I believe the "human problem" here is that the one tends to gloss over "local variable VARNAME", because it describes VARNAME and you already think you know what that is, so you don't stop to think about it.
The following would be better in this regard, IMO:
"Variable VARNAME is local in FUNCNAME, but doesn't have a value at line 123"
+1
participants (12)
-
anatoly techtonik
-
Chris Angelico
-
Glenn Linderman
-
Jan Matějek
-
Nick Coghlan
-
R. David Murray
-
Rob Cliffe
-
Sam Partington
-
Skip Montanaro
-
Steven D'Aprano
-
Terry Reedy
-
Ulrich Eckhardt