I was define a global variables which I wanted to change / give an actual value in a function.
When I tried to run it, I had an error message that informing the global variable is undefined.
please support, thanks. this is my code:
script_name = 'R2M_delayer.py'
recipe_name = 'R2M_E2E_delayer_NR_Ver_5.1'
global images
global metrology_images
logged_date = str(datetime.datetime.now()).split()[0]
NR_log = 'NR_' + logged_date + '.log'
images_output_dir_path = '/usr/local/insight/results/images/toolsDB/lauto_ptest_s' + str(datetime.datetime.now()).split()[0] + '/w3'
metro_images_dir_path = find_dir_path_delayer.get_delayer_images_dir_path()
metro_callback_dir_path = '/usr/local/disk2/unix_nt/R2M/RecipeRun'
def images_check():
estimated_num_of_images = 6640 # Hard codded for Sanity wafer #3
Actual_Images_List = os.listdir(images_output_dir_path)
images = len(Actual_Images_List)
if images >= estimated_num_of_images or images < 7000:
return True, images
print("\nImages quantity is not equal to the actual images in results folder.\n")
return False
print(' ' + str(images) + ' images were send.\n')
Problem has solved. I defined my global variables as fields in class and I was revalued that values of the fields in the functions.
The global keyword goes inside the function. That allows you to call that variable outside the function. If you declare the variable outside the function, you don't need it. By the way, you're returning images anyway. It is much better to return the value instead of modifying global variables, because it may return its reference instead. Global variables are not a good practice because it can """mess up""" with your allocated local memory for your program. I recommend using the garbage collector library gc.collect() to collect any data of a global variable you are not using or managing.
Declare global variables inside function definition, otherwise the scope of variables in function is always local.
To avoid "variable is not defined" error you can initiate them in the main code with some default value, e.g., images = None.
Agree with previous answer, try to not use global variables.
Related
This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 6 months ago.
I am using the PyQt library to take a screenshot of a webpage, then reading through a CSV file of different URLs. I am keeping a variable feed that incremements everytime a URL is processed and therefore should increment to the number of URLs.
Here's code:
webpage = QWebPage()
fo = open("C:/Users/Romi/Desktop/result1.txt", "w")
feed = 0
def onLoadFinished(result):
#fo.write( column1[feed])#, column2[feed], urls[feed])
#feed = 0
if not result:
print "Request failed"
fo.write(column1[feed])
fo.write(',')
fo.write(column2[feed])
fo.write(',')
#fo.write(urls[feed])
fo.write(',')
fo.write('404,image not created\n')
feed = feed + 1
sys.exit(1)
save_page(webpage, outputs.pop(0)) # pop output name from list and save
if urls:
url = urls.pop(0) # pop next url to fetch from list
webpage.mainFrame().load(QUrl(url))
fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
fo.write(',')
fo.write(column2[feed])
fo.write(',')
#fo.write(urls[feed])
fo.write(',')
fo.write('200,image created\n')
feed = feed + 1
else:
app.quit() # exit after last url
webpage.connect(webpage, SIGNAL("loadFinished(bool)"), onLoadFinished)
webpage.mainFrame().load(QUrl(urls.pop(0)))
#fo.close()
sys.exit(app.exec_())
It gives me the error:
local variable feed referenced before the assignment at fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
Any idea why?
When Python parses the body of a function definition and encounters an assignment such as
feed = ...
Python interprets feed as a local variable by default. If you do not wish for it to be a local variable, you must put
global feed
in the function definition. The global statement does not have to be at the beginning of the function definition, but that is where it is usually placed. Wherever it is placed, the global declaration makes feed a global variable everywhere in the function.
Without the global statement, since feed is taken to be a local variable, when Python executes
feed = feed + 1,
Python evaluates the right-hand side first and tries to look up the value of feed. The first time through it finds feed is undefined. Hence the error.
The shortest way to patch up the code is to add global feed to the beginning of onLoadFinished. The nicer way is to use a class:
class Page(object):
def __init__(self):
self.feed = 0
def onLoadFinished(self, result):
...
self.feed += 1
The problem with having functions which mutate global variables is that it makes it harder to grok your code. Functions are no longer isolated units. Their interaction extends to everything that affects or is affected by the global variable. Thus it makes larger programs harder to understand.
By avoiding mutating globals, in the long run your code will be easier to understand, test and maintain.
Put a global statement at the top of your function and you should be good:
def onLoadFinished(result):
global feed
...
To demonstrate what I mean, look at this little test:
x = 0
def t():
x += 1
t()
this blows up with your exact same error where as:
x = 0
def t():
global x
x += 1
t()
does not.
The reason for this is that, inside t, Python thinks that x is a local variable. Furthermore, unless you explicitly tell it that x is global, it will try to use a local variable named x in x += 1. But, since there is no x defined in the local scope of t, it throws an error.
As the Python interpreter reads the definition of a function (or, I think, even a block of indented code), all variables that are assigned to inside the function are added to the locals for that function. If a local does not have a definition before an assignment, the Python interpreter does not know what to do, so it throws this error.
The solution here is to add
global feed
to your function (usually near the top) to indicate to the interpreter that the feed variable is not local to this function.
in my case that exact same error was triggered by a typo !
I thought my my var name was
varAlpha
but in the code i had defined
varalpha
& got the error
UnboundLocalError: local variable 'varAlpha' referenced before assignment
when calling varAlpha
I hope it helps somebody one day searching for that error & wondering (as my search for that error led me here while being unrelated with the use of global or not global which was a head scratcher !)
You can do like this for the function scope
def main()
self.x = 0
def incr():
self.x += 1
for i in range(5):
incr()
print(self.x)
This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 6 months ago.
I am using the PyQt library to take a screenshot of a webpage, then reading through a CSV file of different URLs. I am keeping a variable feed that incremements everytime a URL is processed and therefore should increment to the number of URLs.
Here's code:
webpage = QWebPage()
fo = open("C:/Users/Romi/Desktop/result1.txt", "w")
feed = 0
def onLoadFinished(result):
#fo.write( column1[feed])#, column2[feed], urls[feed])
#feed = 0
if not result:
print "Request failed"
fo.write(column1[feed])
fo.write(',')
fo.write(column2[feed])
fo.write(',')
#fo.write(urls[feed])
fo.write(',')
fo.write('404,image not created\n')
feed = feed + 1
sys.exit(1)
save_page(webpage, outputs.pop(0)) # pop output name from list and save
if urls:
url = urls.pop(0) # pop next url to fetch from list
webpage.mainFrame().load(QUrl(url))
fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
fo.write(',')
fo.write(column2[feed])
fo.write(',')
#fo.write(urls[feed])
fo.write(',')
fo.write('200,image created\n')
feed = feed + 1
else:
app.quit() # exit after last url
webpage.connect(webpage, SIGNAL("loadFinished(bool)"), onLoadFinished)
webpage.mainFrame().load(QUrl(urls.pop(0)))
#fo.close()
sys.exit(app.exec_())
It gives me the error:
local variable feed referenced before the assignment at fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
Any idea why?
When Python parses the body of a function definition and encounters an assignment such as
feed = ...
Python interprets feed as a local variable by default. If you do not wish for it to be a local variable, you must put
global feed
in the function definition. The global statement does not have to be at the beginning of the function definition, but that is where it is usually placed. Wherever it is placed, the global declaration makes feed a global variable everywhere in the function.
Without the global statement, since feed is taken to be a local variable, when Python executes
feed = feed + 1,
Python evaluates the right-hand side first and tries to look up the value of feed. The first time through it finds feed is undefined. Hence the error.
The shortest way to patch up the code is to add global feed to the beginning of onLoadFinished. The nicer way is to use a class:
class Page(object):
def __init__(self):
self.feed = 0
def onLoadFinished(self, result):
...
self.feed += 1
The problem with having functions which mutate global variables is that it makes it harder to grok your code. Functions are no longer isolated units. Their interaction extends to everything that affects or is affected by the global variable. Thus it makes larger programs harder to understand.
By avoiding mutating globals, in the long run your code will be easier to understand, test and maintain.
Put a global statement at the top of your function and you should be good:
def onLoadFinished(result):
global feed
...
To demonstrate what I mean, look at this little test:
x = 0
def t():
x += 1
t()
this blows up with your exact same error where as:
x = 0
def t():
global x
x += 1
t()
does not.
The reason for this is that, inside t, Python thinks that x is a local variable. Furthermore, unless you explicitly tell it that x is global, it will try to use a local variable named x in x += 1. But, since there is no x defined in the local scope of t, it throws an error.
As the Python interpreter reads the definition of a function (or, I think, even a block of indented code), all variables that are assigned to inside the function are added to the locals for that function. If a local does not have a definition before an assignment, the Python interpreter does not know what to do, so it throws this error.
The solution here is to add
global feed
to your function (usually near the top) to indicate to the interpreter that the feed variable is not local to this function.
in my case that exact same error was triggered by a typo !
I thought my my var name was
varAlpha
but in the code i had defined
varalpha
& got the error
UnboundLocalError: local variable 'varAlpha' referenced before assignment
when calling varAlpha
I hope it helps somebody one day searching for that error & wondering (as my search for that error led me here while being unrelated with the use of global or not global which was a head scratcher !)
You can do like this for the function scope
def main()
self.x = 0
def incr():
self.x += 1
for i in range(5):
incr()
print(self.x)
I made an error while defining a function within a class, yet it doesn't change how the code operates during runtime.
The error I made was using a global variable when I mean to use an instanced variable.
What I meant to write was:
self._map_data[screen_pos_layer][y][x] = selected_material
Instead, I wrote:
map_data[screen_pos_layer][y][x] = selected_material
However, the intended functionality (change the color of an LED) doesn't change, no matter if it's the instanced variable or the global variable. The function that actually writes the color into the LED is in a different class.
I thought that could only happen if I include global <variable> ? I have very little experience with Python but I'm sure this was true.
class Tools(object):
def __init__(self, _map_data):
self._map_data = _map_data
def paint(self, event):
if selected_tool == select_paint and selected_color != -1:
for j in range(cursor_size_y):
for i in range(cursor_size_x):
y = screen_pos_y + cursor_pos_y + j
x = screen_pos_x + cursor_pos_x + i
map_data[screen_pos_layer][y][x] = selected_material
else:
return
moveCursor(event)
tools = Tools(map_data)
# this is a Tkinter object
window.bind_all("<Control-Up>", tools.paint)
I tried searching for this but I could only find posts about people wanting to use a global variable in a class, I specifically am trying not to.
Evidently your code has previously created a global map_data variable, so the code you're showing is not re-creating the map_data variable, it is only modifying an element of the existing variable. The existing variable is found via regular name lookup, and so in this case it is found in the global context.
I have a program in python. part of the program is:
suggestengines = get_suggestengines(suggestengines)
sleeptimer = sleepcount * len(suggestengines)
seeds = get_seeds(dummydata=False)
For further programming I want to make a function of it:
def first_step():
suggestengines = get_suggestengines(suggestengines)
sleeptimer = sleepcount * len(suggestengines)
seeds = get_seeds(dummydata=False)
Now I get an error for "suggestengines" that I want to pass into get_suggestengines(). Also sleep timer and seeds get a marker, that I don't use them in the rest of the program. I googled it and got the answer: Us global. So I added global for everything
def first_step():
global suggestengines
global sleeptimer
global seeds
suggestengines = get_suggestengines(suggestengines) #which engines to run?
sleeptimer = sleepcount * len(suggestengines)
seeds = get_seeds(dummydata=False)
In further part of the program I have
for seed in tqdm(seeds, leave=True):
there the program gives me an error vor seeds in tqdm. If I change it to also make a def of it like:
def partTwo():
for seed in tqdm(seeds, leave=True):
Then I don't get an error anymore although I didn't used global. Can someone explain me why and if I need to use global in part 2 also?
The statement
global <identifier>
tells python that <identifier> should refer to a global when used in assignments. This is necessary in functions that change globals because Python has no syntactical difference between declaring a variable and assigning to an existing variable. The default in python is to have assignments in functions create new variables, rather than change global state.
When you just read from a variable there is no syntactic ambiguity, so Python will just use whatever variable it finds (i.e. global if there is no local one).
Example:
a = 1
def foo():
a = 2 # this will create a new, local variable a
def bar():
global a # "when I refer to a, I mean the global one"
a = 2 # this will change the global variable a
If no global with the specified name exists, the global statement itself will not create a new global variable, but any following assignment will. E.g. given the following:
def x():
global c
def y():
global c
c = 1
def z()
print c
x(); z() would be an error(global name 'c' is not defined), while y(); z() would print 1.
seeds hasn't been initialized yet by the time the for loop is hit, since its initialization is part of a def that hasn't been called yet. If you put the for loop inside a def then it will be called in the order you call the functions, so the interpreter won't complain until you actually use it.
The only thing to keep in mind here is this: use variables after they have been initialized.
I'd like to do something like this, but I get a SyntaxWarning and it doesn't work as expected
RAWR = "hi"
def test(bool):
if bool:
RAWR = "hello" # make RAWR a new variable, don't reference global in this function
else:
global RAWR
RAWR = "rawr" # reference global variable in this function
print RAWR # if bool, use local, else use global (and modify global)
How do I get this to work? Passing in True or False modifies the global variable.
You cannot. Within a scope, a specific name refers either to a local variable, or to a non-local (e.g. global, or from an outer function) variable. Not both. The global RAWR line makes RAWR a global for the entire scope (that's why you get a warning, it doesn't do what you think it does), just like assignment to a variable makes it local for the entire scope. Edit: Thanks to veredesmarald, we now know it is in fact a syntax error in Python 2. This half of my answer only applies to Python 3 apparently.
You should just use a differently-named local variable, and in the branch where you want to "promote" it to a global, set the global and the local variable. (Or just don't use globals at all.)
The only easy way you can go would be
RAWR = "hi"
def test(newone):
if newone:
lR = "hello" # make RAWR a new variable, don't reference global in this function
else:
global RAWR
lR = RAWR # reference global variable in this function
print lR # if bool, use local, else use global (and modify global)
# modify lR and then
if not newone:
RAWR = lR
Another way, however, could be to abuse the concept of classes and objects to your purposes.
class store_RAWR(object):
RAWR = "hi"
def __init__(self, new): self.RAWR = new
def test(newone):
if newone:
myR = store_RAWR("hello") # get a (temporary) object with a different string
else:
myR = store_RAWR # set the class, which is global.
# now modify myR.RAWR as you need
But this requires other program parts which use the global name to be changed as well.