Search code examples
pythontkintermultiprocessingttk

How to get return value of sub process in main process


I want to start a webserver if the user does click on a button. Therefore I have written the following code:

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import time
from multiprocessing import Process


class MainWindow(ttk.Frame):

    def __init__(self, parent):
        self.parent = parent
        ttk.Frame.__init__(self, master=self.parent)
        self.parent.grab_set()
        self.parent.title("Test_Program")
        self.parent.geometry("500x500")
        ttk.Button(self.parent, text="Start Web-Server", command=self.start_webserver).pack()

    def start_webserver(self):
        if __name__ == '__main__':
            loading_screen = LoadingScreen(self)
            result = [0]
            sub_process = Process(target=start_webserver, args=(result,))
            sub_process.start()
            sub_process.join()
            sub_process.terminate()
            loading_screen.destroy()
            if result[0] == 0:
                messagebox.showinfo("Webserver Status", "Webserver is running!")
            else:
                messagebox.showerror("Webserver Status", "Webserver can't be started an Error occured!")


class LoadingScreen(tk.Toplevel):

    def __init__(self, parent):
        self.parent = parent
        tk.Toplevel.__init__(self, master=self.parent)
        self.geometry("200x50")
        self.title("Loading Screen")
        self.transient(self.parent)
        self.grab_set()
        ttk.Label(self, text="Copying data!").pack()
        status_bar = ttk.Progressbar(self, length=180, mode="indeterminate")
        status_bar.start(5)
        status_bar.pack()

    def __del__(self):
        if isinstance(self.parent, tk.Toplevel):
            self.parent.grab_set()


def start_webserver(result):
    time.sleep(2) # This does represent the time thats necessary to start the webserver
    result[0] = 1

def main():
    root = tk.Tk()
    main_window = MainWindow(root)
    main_window.pack()
    root.mainloop()

if __name__ == "__main__":
    main()

If I click on "start webserver" its two seconds frozen because of time.sleep(2) and no progress bar does get displayed. Afterwards its done. I don't know why there is no progressbar displayed. I have used an array named "result" as parameter to get the return value of start_webserver(result) from sub_process to main_process. Unfortunately this is not working too because the value of "result[0]" stays 0. I don't know what to do. The idea of using an array I have found on stackoverflow too.

Here is the Link: how to get the return value from a thread in python?


Solution

  • I have found out an answer by my own. Thanks for your help join() wasn't right. I have done it a different way and closing the "loading_screen" as well as opening the messagebox after the job has been done in the second thread.

    That's the Code:

    import tkinter as tk
    import tkinter.ttk as ttk
    from tkinter import messagebox
    import time
    from threading import Thread
    
    
    class MainWindow(ttk.Frame):
    
        def __init__(self, parent):
            self.parent = parent
            ttk.Frame.__init__(self, master=self.parent)
            self.parent.grab_set()
            self.parent.title("Test_Program")
            self.parent.geometry("200x50")
            ttk.Button(self.parent, text="Start Web-Server", command=self.start_webserver).pack()
    
        def start_webserver(self):
            if __name__ == '__main__':
                loading_screen = LoadingScreen(self)
                thread = Thread(target=start_webserver, args=(loading_screen, ))
                thread.start()
    
    
    class LoadingScreen(tk.Toplevel):
    
        def __init__(self, parent):
            self.parent = parent
            tk.Toplevel.__init__(self, master=self.parent)
            self.geometry("200x50")
            self.title("Loading Screen")
            self.transient(self.parent)
            self.grab_set()
            ttk.Label(self, text="Copying data!").pack()
            status_bar = ttk.Progressbar(self, length=180, mode="indeterminate")
            status_bar.start(2)
            status_bar.pack()
    
        def __del__(self):
            if isinstance(self.parent, tk.Toplevel):
                self.parent.grab_set()
    
    
    def start_webserver(widget):
        return_val = do_some_stuff()
        if return_val:
            widget.destroy()
            messagebox.showinfo("Webserver Status", "Webserver is running!")
        else:
            widget.destroy()
            messagebox.showerror("Webserver Status", "Webserver can't be started an Error occured!\n"
                                                     "Please look inside 'Logfiles/logfile' for more details.")
    
    
    def do_some_stuff():
        time.sleep(2) # This does represent the time thats necessary to start the webserver
        return True
    
    
    def main():
        root = tk.Tk()
        main_window = MainWindow(root)
        main_window.pack()
        root.mainloop()
    
    
    if __name__ == "__main__":
        main()