Skip to content
Advertisement

Python Tkinter variable not updating in other thread

import tkinter as tk
import threading
import urllib.request
import pyperclip
import datetime
import time
import winsound

window = tk.Tk()
window.title("Pinger")
window.protocol("WM_DELETE_WINDOW", window.destroy)

mainvar = tk.StringVar(window) #creation of a variable
mainvar.set('realm') #set variable

window.iconbitmap('icon1.ico')

menu = tk.OptionMenu(window, mainvar, "1", "2", "3", "4", "5") #drop down
menu.pack()

global current_event_id 
current_event_id = '-1'

def change_dropdown(*args):
    #print(mainvar.get()) #no need for flush
    if (mainvar.get() == "1"):
        window.iconbitmap('icon1.ico')
        current_event_id = '-1'
    elif (mainvar.get() == "2"):
        window.iconbitmap('icon2.ico')
        current_event_id = '-2'
    elif (mainvar.get() == "3"):
        window.iconbitmap('icon3.ico')
        current_event_id = '-3'
    elif (mainvar.get() == "4"):
        window.iconbitmap('icon4.ico')
        current_event_id = '-4'
    elif (mainvar.get() == "5"):
        window.iconbitmap('icon5.ico')
        current_event_id = '-5'

mainvar.trace('w', change_dropdown) #add an event listener to the main variable and link it to the change_dropdown function

def run():
    link = "https://website"
    m2 = ''
    while True:
            m1 = str(datetime.datetime.now().minute)
            s1 = datetime.datetime.now().second
            if (s1 == 59 and m1 != m2):
                    m2 = m1
                    f = urllib.request.urlopen(link)
                    myfile = f.read() 
                    text = myfile.decode('utf-8')
                    events = text.split('n')

                    i = 0
                    while True:
                            keys = events[i].split('|')
                            time = keys[5].split(':')[1]
                            key = keys[6]
                            if (time != m1):
                                    break
                            if (event_id == current_event_id):
                                    winsound.Beep(440,500)
                                    pyperclip.copy(key)
                                    print(key)
                            i += 1

control_thread = threading.Thread(target=run)
control_thread.start()


window.mainloop()


So I have a python script which accesses a website every minute, reads the page, and pings me if a certain data was placed on the website in that minute. I’m expanding this script to have a menu and a way to switch between different data points. The GUI and the script work well independently. However, the variable current_event_id does not update properly in my control_thread. I can mess with the GUI correctly; for instance, the icons change properly. However, the loop in run() does not reflect the change in current_event_id. I am hoping there is some simple workaround.

Advertisement

Answer

A classic pitfall with global variables in Python: In your change_dropdown function, you need to declare global curent_event_id before setting it, otherwise you are actually setting a local variable which is forgotten as soon as the function exits.

A simple demonstration:

x = "old x"
y = "old y"

def changeX():
    x = "new x"

def changeY():
    global y
    y = "new y"

changeX()
changeY()
print(x, y)

This will print old x new y.

Also, AFAIK, the use of global outside a function has no effect in Python, since it only says: “Use or create this variable in the module variable namespace”. It is not needed as an additional declaration if you are introducing a variable in your module. So, in your case, if you just initialize your variable as:

current_event_id = '-1'

This will have the same effect as the old

global current_event_id
current_event_id = '-1'
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement