I have a class with some variables declared as globals in the first method. Another subsequent method starts a thread, and the problem is that python doesn't recognize those global variables after t.start(). Here is how the program works: 1) user can click "YES"-button on tkinter window 2) program then starts to upload data into database. This step takes a while (2-5 minutes) and to prevent UI from freezing during the upload, the program starts a thread that performs the sql stuff. At same time, the program clears widgets from the window and replaces them with new widgets (a progress bar and a text field). 3) after upload is completed, the program again refresh the tkinter window with new buttons and a scrollbox.
Here is the code snippet:
class Application(tk.Frame): def __init__(self, parent): #do some init here.. def initUI(self): global text1, text2, button_no, button_yes, progress_bar #here are the globals frame1 = tk.Frame(self) frame1.pack() text1 = tk.Label(self, text="Do you want to upload a new log file?", background="white") button_yes = tk.Button(self, text="YES", command=self.removeButtonYes) button_no = tk.Button(self, text="NO", command=self.removeButtonNo) text1.pack() button_yes.pack() button_no.pack() self.pack(fill=tk.BOTH, expand=1) def removeButtonNo(self): #do something here def removeButtonYes(self): text1.pack_forget() #first three lines clear those original three widgets button_no.pack_forget() button_yes.pack_forget() #then add some text with the progress bar text2 = tk.Label(self, text="Transferring data. Please wait...", background="white") text2.pack() progress_bar = ttk.Progressbar(self, orient="horizontal", length=100, mode="indeterminate") progress_bar.pack() progress_bar.start(100) #initialize a thread to prevent the UI from freezing during sql inserts t = threading.Thread(target=self.writeLogtoDatabase) t.start() def writeLogtoDatabase(self): #open db connection, upload data and close db self.clearUI() #call a method to clear the progress bar and info text def clearUI(self): text2.pack_forget() progress_bar.pack_forget()
It just throws following error message:
Exception in thread Thread-1: Traceback (most recent call last): File "c:\python27\lib\threading.py", line 810, in __bootstrap_inner self.run() File "c:\python27\lib\threading.py", line 763, in run self.__target(*self.__args, **self.__kwargs) File "C:\Python27\test\testdb2.py", line 94, in writeLogtoDatabase self.clearUI() File "C:\Python27\test\testdb2.py", line 98, in clearUI text2.pack_forget() NameError: global name 'text2' is not defined
Why? As you can see, I can call those variables outside the method where they are declared. Has this something to do with threading - a thing, that I am not very familiar with?
Unless I don't forget those text2 and progress bar widgets, they will show up in the last window which is not desired functionality.
You should add
global text2 on the
removeButtonYes method (and also for
progress_bar, otherwise you'll have the same problem again). It's completely useless to add a
global text2 statement in a function that doesn't define that variable.
Also I don't see the advantage of using a global variable in this case, except that it's really easy to create bugs. Why don't you simply use an instance attribute