1

When I execute a testing script in my company's Python project, I got an error as below:

UnboundLocalError: local variable 'a' referenced before assignment

I wrote some simpler code to reproduce the issue, it has 2 files.

vars.py file:

#!/usr/bin/env python
a = 'aaa'

script.py file:

#!/usr/bin/env python
from vars import *


def myFunc1():
    print a

    if False:
        a = '111'

    print a

myFunc1()

Execute the code:

$ python --version
Python 2.7.10
$ python script.py 
Traceback (most recent call last):
  File "script.py", line 13, in <module>
    myFunc1()
  File "script.py", line 6, in myFunc1
    print a
UnboundLocalError: local variable 'a' referenced before assignment
$ 

I googled the UnboundLocalError and found some useful information like:

UnboundLocalError: local variable 'L' referenced before assignment Python

UnboundLocalError in Python

According to the answers in above 2 questions, if I add a global a after the def myFunc1(): line in script.py file, the error is gone.

The thing I don't understand is removing the if condition from myFunc1 can also make it work...

Community
  • 1
  • 1
Shawn Hu
  • 349
  • 2
  • 8
  • Python determines local variables _statically at compile time_. Whenever there is an assignment to a variable anywhere in a function, the variable is considered local in the _whole function body_, including the first `print` statement. – Sven Marnach Apr 21 '16 at 18:53
  • It's explained at the links that OP already found, but we have a better canonical now. – Karl Knechtel Sep 09 '22 at 14:35

2 Answers2

1

Assigning to a name makes the name a local variable, which means that you can't assign to a non-local variable without extra syntax. In your code:

from vars import *

def myFunc1():
    print a         # the local variable `a` is used before it is created
    if False:
        a = '111'   # this creates a local variable `a`
    print a

adding global a as the first line in myFunc1 will tell Python that it shouldn't create a local variable when it sees an assignment to a. It will almost certainly not do what you expect though (assuming you expect the a in vars to be changed..). from vars import * creates local "copies" of the names in vars, and using the global statement just means that you are assigning to this module's a variable. Other modules that import vars will not see the assignment.

Removing the if statements also removes the assignment, which is why that eliminates the error.

I understand that from vars import * and using variables in the vars.py is not a good design... But I can't pass all needed variables to the function since the function may use 20+ variables from the vars.py in company's project

shudder.. please refactor.

For this particular problem you should use this pattern:

import vars

def myFunc1():
    print vars.a
    if False:
        vars.a = '111'
    print vars.a
thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • Thanks thebjorn for the answer! You are right! If I use `global a`, the `a` variable is only changed in `myFunc1` when an assignment is executed. If I use `vars.a`, the `a` variable is changed after `myFunc1` call. You have resolved my problem, thanks again! P.s. the company's project is used for UI testing, and vars.py stores many common UI element names. Normally we should not change variables from vars.py, but on linux, some UI element names changed depend on their content. :( – Shawn Hu Apr 22 '16 at 00:56
0

You should be passing the value to the function, not relying on global variables. Also if False doesn't really do anything, since it will always return True. You may have meant to say if variable:

#!/usr/bin/env python
from vars import *


def myFunc1(x):
    print x

    if x:
        x = '111'

    print x

myFunc1(a)
Chris
  • 15,819
  • 3
  • 24
  • 37
  • 1
    Thanks for your answer! It's just a sample code, the `if` condition statement is needed in company's project. The script.py in my company's project was designed to run on both Windows and Linux. Changing the `if False:` statement to `if not onWindows():` makes more sense. When I run the script on Windows, the statement in `if` does not execute. – Shawn Hu Apr 21 '16 at 14:53
  • I understand that `from vars import *` and using variables in the vars.py is not a good design... But I can't pass all needed variables to the function since the function may use 20+ variables from the vars.py in company's project... – Shawn Hu Apr 21 '16 at 14:58