I am trying to figure out what the best practice is to execute a parallel function with tkinter, that when completed, changes the GUI, without blocking the mainloop while running.
The specific case is the following, I am trying to check if a file exist, and if it does, do some checks on the content. Based on the result, I want to update the GUI to indicate the result of the check. But as the file is on a network location, it can take some time to complete the check, and I don't want to block the program while the check is performed.
I found an example at https://www.oreilly.com/library/view/python-cookbook/0596001673/ch09s07.html that I could probably make work for this purpose, but is this still a valid way of doing it, or are there better?
UPDATE: I updated the code based on the response from TheLizzard. Would this be a valid implementation? Seems to be working from what I can tell.
import threading
import tkinter as tk
import os
import time
class GUI:
"""Main GUI"""
def __init__(self):
"""Start the GUI"""
self.gui_root = tk.Tk()
self.gui_root.minsize(300, 50)
# Button to show test if GUI is responsive while checking for file
self.button = tk.Button(self.gui_root, text="Button", command=lambda: print("text"))
self.button.pack()
self.label = tk.Label(self.gui_root, text="This is a label")
self.label.pack()
self.check_has_completed = False
self.result = None
new_check = threading.Thread(target=find_file, args=(self,))
new_check.start()
self.check_for_file()
def check_for_file(self):
"""Check if the file exist"""
if self.check_has_completed:
print(f"Done with the check, result were: {self.result}")
if self.result:
self.label.configure(text="Found file and passed test")
else:
self.label.configure(text="Didn't find file, or test was not passed")
return None
self.gui_root.after(500, self.check_for_file)
print(f"Response pending...")
def find_file(_gui: GUI):
"""Dummy function, check if a file exist, and if it does, do some work with it, and return result"""
print("Check started")
potential_path = os.path.join(os.getcwd(), "Test file.txt")
time.sleep(5) # Dummy to simulate processing time
if os.path.isfile(potential_path):
# Do some checks here, then return boolean if checks passed
if True:
_gui.result = True
_gui.check_has_completed = True
return True
# Return false if file was found, or checks didn't pass
_gui.result = False
_gui.check_has_completed = True
return False
if __name__ == '__main__':
gui = GUI()
gui.gui_root.mainloop()