Search code examples
pythonvariablestkinterglobalnested-function

How to create global variable in nested function using tkinter?


I wrote some code using tkinter and some nested functions (see code below) and get the warning in pycharm "Global variable 'value' is undefined at the module level". The program works as intended (the window title is renamed to 'text 0') but i still get the warning... What do i have to change to get rid of this warning? (the program is more complex, i need to start it like it does, with window.after and i also need all the functions)

from tkinter import *

def function_1():
   global value
   window.title("text " + value)

def function_2():
   def function_3():
       global value
       value = ent.get()
       if value == '0':
          function_1()
   ent = Entry()
   ent.pack()
   button = Button(text="ok", command=function_3)
   button.pack()


window = Tk()
window.after(0, function_2)
window.mainloop()

Solution

  • The global keyword is used inside a function to control assignment to a variable. Normally within a function value = "bar" creates a "value" in the local function namespace. global value in that same function tells python to use the global namespace instead.

    In your current code, the module level value variable will not come into existence until function_3 is called. Anything that tries to use value before function_3 is called will get a NameError. function_1 is a case in point; if it is called before function_3, you have an error. It may be that your code can never call function_1 before function_3 but that is difficult for a linter or future maintiainers of the code to know. That's why you get the warning.

    The solution is to set a default for value that is sensible for the program. I don't know what works for you, but here is an example that throws up a message. BTW, global value is not needed in function_1. Its job is to control assignment, you can read global variables without any additional annotation.

    from tkinter import *
    
    value = None
    
    def function_1():
       if value is not None:
           window.title("text " + value)
       else:
           import tkinter.messagebox
           tkinter.messagebox.showerror("Error", "Do the thing before the thing")
    
    def function_2():
       def function_3():
           global value
           value = ent.get()
           if value == '0':
              function_1()
    
       ent = Entry()
       ent.pack()
       button = Button(text="ok", command=function_3)
       button.pack()
      
    window = Tk()
    window.after(0, function_2)
    window.mainloop()