Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Global not working why?
#1
I know Global's are looked down upon, but in this instance I don't know what else to do. Any in the function at top the print statement works just fine as you will see in the out put. But when same print statement made in another function at the bottom, I just get an empty list.

def complete_form():
	global scratched_list
	scratched_list = []
	for i, var in enumerate(scratched):    
		scratched_list.append(var.get())   	
	
	print(scratched_list)
	


	#SET UP SCFRATCH WINDOW

def get_scratches(horses_name):
	global namevar1
	global scratched
	

	scratched =[]
	

	scratches = Toplevel()
	

	scratches.title("Handifast Version 13.0 Scratch Window")

	scratches.iconbitmap("c:/guis/racehorse.ico")

	width_of_window = 500
	height_of_window = 700
	

	screen_width= scratches.winfo_screenwidth()
	screen_height = scratches.winfo_screenheight()
	x_coordinate = (screen_width/2) - (width_of_window/2)
	y_coordinate = (screen_height/2) - (height_of_window/2)
	scratches.geometry("%dx%d+%d+%d" % (width_of_window,height_of_window,x_coordinate,y_coordinate ))
	my_scratch_label= Label(scratches, text = track_abrev + "  " + "Race  " + str(race_number), fg= "#473DAD", font = ("sans_serif" , 11, 'bold')).place(x=200, y=5)
	my_scratch_label1= Label(scratches, text ="Select Horses to Scratch  ", fg= "#F50808", font = ("sans_serif" , 14)).place(x=140, y=25)
	

	
	#create_checkboxes FOR SCRATCH WINDOW()
	namevar1 = StringVar()

	xx = 55
	yy = 50

	h = (len(horses_name))
	count = 0
	

	for i in range(h):
		var = BooleanVar()
		scratched.append(var)
		button = Checkbutton(scratches, text = str(i+1), variable = var, onvalue = True, offvalue = False).place(x=10, y=yy)
		#button.deselect()
		my_scratch_label2= Label(scratches, text =horses_name[count], fg= "black", font = ("sans_serif" , 10, 'bold')).place(x=xx, y=yy)
		yy+=25
		count+=1
	process_scratch_button= Button(scratches, text="Process Scratches", bg='#16EF1A', width = 15, command=complete_form)		
	process_scratch_button.place(x=200, y=600)		




# LOAD TRACK by racenumber TO HANDICAP
def load_track_to_Handi():
	my_tracklabel= Label(root, text ="                                                                               ", fg= "#F50808", font = ("sans_serif" , 16)).place(x=380, y=430)
	read_csvfile_into_array()
	
		
	global track_abrev
	global race_number
	global xx
	global horses_name
	
	global hcount
	global horse_count
	
	global horses_info
	
	global cnt
	

	horse_array = np.arange(2100).reshape(20,105)
	
	#if fileFound ==True:
	
	horses_info =  [] 
	horse_single_race_info = []	 
	horse_saddle = []
	horses_name = []
	hcount = 0
	
	
	with open( 'C://guis/f_racefiles/'+ track_abrev + '.csv' , 'r') as race_file:

		
		df = pd.read_csv(race_file, header =None)
		race_data = df[(df[1] == race_number)]
		

		 
		#print(race_data[18])
		#print(df[18])
		xx = df.iloc[ :, 0: 105 ].values
		#race_data.set_index(18, inplace = True)
		#print(race_data.loc[0, 18])
		
#READ FILE AND PULL OUT HORSES AND HORSE INFO FOR SELECTED RACE AND TRACK
		#for cnt in range(0,len(xx)):
			
		for cnt in range(0,len(xx)):
			
        	
			if int(xx[cnt][1])== int(race_number):
				horses_name.append(xx[cnt][18])
							 
		get_scratches(horses_name)
		       
		
		#for i in range(0,len(race_data)):
			#if scratched_list[i] == 'True':
				#race_data.drop(i)		
								 
		print(scratched_list)  #Here is where the error is thrown. says not defined but scratched_list is a global.
Here is result from the two print statements.

$ python processing.py
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Milford\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "processing.py", line 130, in select_track
load_track_to_Handi()
File "processing.py", line 1467, in load_track_to_Handi
print(scratched_list)
NameError: name 'scratched_list' is not defined
[False, False, True, False, False, False] # This is top print statement at moment scratch_list is created. Error is from bottom print statement.
Reply
#2
I am not sure but when you define a variable in a function as global, it must first exist in the global scope. Where in your code is "scratched_list" defined on the global level?
Reply
#3
if you must use them (bad practice) see: https://www.geeksforgeeks.org/global-keyword-in-python/
which gives some examples.

globals should be avoided unless absolutely necessary.
Why?
  • suppose function B wants to save a value in global X, do some work, and then grab the value of Global X for another operation.
  • meanwhile, function A modifies global X for something it needs to do
    when function B grabs value from X, it gets the value that function A stored there, not what it expected.
  • What you have is a debugging nightmare.
  • If you're working on a critical piece of code, this could have devastating consequences.

I have been working with software since 1968, and during that time, only used globals in the early days, and I don't think ever after the 'C' language appeared.
variables should be passed to functions, not fetched from global variable. and returned from the function if required.
Reply
#4
@Milfredo, Are you sure that you call complete_form() before load_track_to_Handi()?
Reply
#5
No. because the track and the race number has to be selected by user before call to Handi. After call to handi then call to get scratches which then calls complete form, which is where scratched list originates. Where can I define scratched list, as everything is a function in my program?

iBreedan, I don't know where to define scratched list as everything is a function in my program.
Reply
#6
This is a minimal example to show what is happened:

In [1]: def a():
   ...:     global x
   ...:     x = 3
   ...:

In [2]: def b():
   ...:     print(f'x-value:{x}')
   ...:
Error:
In [3]: b() --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-3-3bf86fc5afda> in <module> ----> 1 b() <ipython-input-2-18573d0c41e2> in b() 1 def b(): ----> 2 print(f'x-value:{x}') 3 NameError: name 'x' is not defined
In [4]: a()

In [5]: b()
x-value:3
If you want to put everything in functions, you can define, a function initialize_all():, where you declare
all globals that you will use further. And call this function at the beginning...
However, as it was mentioned above, this is not a good practice.
Reply
#7
I have tried everything but I can't get access to scratched list after the scratched_list is created in
complete_form().

def complete_form():
	
	global scratched_list
	scratched_list = []

	
	for i, var in enumerate(scratched):    
		scratched_list.append(var.get())   	
	
	print(scratched_list)   # this prints out just fine. But later I need it and just get an empty list.
I am so frustrated.
Reply
#8
That suggests that either something else is clearing the value, or you're not actually reading from the global.

Because globals can be modified anywhere in the code, debugging means looking at every assignment that the variable has throughout your code.

Also, because lists are mutable, it's possible to assign it to something else and unwittingly clear it, thinking you're clearing a copy.

def complete_form():

    global scratched_list
    scratched_list = []


    for i, var in enumerate(['a', 'b', 'c']):
        scratched_list.append(f"{i} {var}")
    return


def something_else():
    my_list = scratched_list # incorrectly assumes this is a local copy
    my_list.clear()          # clears the global as well
    return

complete_form()
print(scratched_list)
something_else()
print(scratched_list)
Output:
['0 a', '1 b', '2 c'] []
Reply
#9
(Oct-02-2020, 07:29 AM)Milfredo Wrote: File "processing.py", line 1467, in load_track_to_Handi

With so many lines in your program all in one file, it's going to be hard to manage and understand it all at once (this is even regardless of the use of globals). You should look at classes, modules and packages as ways to split it up into meaningful pieces.
Reply
#10
Firstly I find your code hard to read and there is no clear flow to it. Its interesting that you have acknowledged that global s are bad, but yet you've used extensively. And I dont buy into the argument that there isnt any other of doing it. Perhaps if your question was to how can i improve this code to remove global s would have gained a lot more help.

I dont believe you have posted the entire code either? For global to be any effective, thye need to defined at the very top and within the function you can refer those variables by prefixing a variable with keyword global. Something like this

scratched_list = []


def complete_form():
    global scratched_list
    scratched_list.append(10)
    print(scratched_list)


def load_track_to_Handi():
    global scratched_list
    print(scratched_list)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Global variables not working hobbyist 9 4,713 Jan-16-2021, 03:17 PM
Last Post: jefsummers
  Global variable does not seem to be global. Columbo 6 3,672 Jul-15-2019, 11:00 PM
Last Post: Columbo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020