[Python-Dev] Improve error message "UnboundLocalError: local variable referenced before assignment"

17 views
Skip to first unread message

anatoly techtonik

unread,
Oct 31, 2012, 3:57:28 PM10/31/12
to python-dev
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.

R. David Murray

unread,
Oct 31, 2012, 4:28:06 PM10/31/12
to python-dev
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
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: http://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Terry Reedy

unread,
Oct 31, 2012, 5:01:07 PM10/31/12
to pytho...@python.org
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

Steven D'Aprano

unread,
Oct 31, 2012, 6:15:57 PM10/31/12
to pytho...@python.org
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

Terry Reedy

unread,
Oct 31, 2012, 9:20:01 PM10/31/12
to pytho...@python.org
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

Chris Angelico

unread,
Oct 31, 2012, 9:45:44 PM10/31/12
to pytho...@python.org
On Thu, Nov 1, 2012 at 12:20 PM, Terry Reedy <tjr...@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

Terry Reedy

unread,
Nov 1, 2012, 1:49:51 AM11/1/12
to pytho...@python.org
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.

Rob Cliffe

unread,
Nov 1, 2012, 4:36:51 AM11/1/12
to pytho...@python.org

On 01/11/2012 01:45, Chris Angelico wrote:
> On Thu, Nov 1, 2012 at 12:20 PM, Terry Reedy <tjr...@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
An excellent idea IMO. +1
Rob Cliffe
> _______________________________________________
> Python-Dev mailing list
> Pytho...@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/rob.cliffe%40btinternet.com

Ulrich Eckhardt

unread,
Nov 7, 2012, 8:57:57 AM11/7/12
to pytho...@python.org
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.
**************************************************************************************

Sam Partington

unread,
Nov 7, 2012, 9:15:34 AM11/7/12
to Ulrich Eckhardt, pytho...@python.org
On 7 November 2012 13:57, Ulrich Eckhardt
<ulrich....@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

Skip Montanaro

unread,
Nov 7, 2012, 9:16:57 AM11/7/12
to Ulrich Eckhardt, pytho...@python.org
> 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

R. David Murray

unread,
Nov 7, 2012, 9:20:19 AM11/7/12
to pytho...@python.org
On Wed, 07 Nov 2012 14:57:57 +0100, Ulrich Eckhardt <ulrich....@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

Nick Coghlan

unread,
Nov 7, 2012, 10:01:59 AM11/7/12
to Ulrich Eckhardt, pytho...@python.org
On Wed, Nov 7, 2012 at 11:57 PM, Ulrich Eckhardt
<ulrich....@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 | ncog...@gmail.com | Brisbane, Australia

Jan Matějek

unread,
Nov 12, 2012, 10:30:41 AM11/12/12
to pytho...@python.org
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.

Glenn Linderman

unread,
Nov 12, 2012, 6:52:15 PM11/12/12
to Jan Matějek, pytho...@python.org
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
Reply all
Reply to author
Forward
0 new messages