Tkinter application 'freezes' while continually polling Pipe for contents (multiprocessing)

后端 未结 4 619
北荒
北荒 2021-01-27 09:21

I have two scripts:

Processor_child.py: Its purpose is to perform a number of data analysis and cleaning operations. This must perform the same operatio

4条回答
  •  攒了一身酷
    2021-01-27 09:40

    It appears that the behaviour you are trying to achieve is to communicate with a function whilst it's running. I think that your problems could be solved by using generators. A generator lets you yield multiple values from a function, and send values to that function.

    Here is some more information on generators if you want to know how they work.

    I'm not entirely sure if this is exactly the behaviour you want from your program, but I have modified your code to use generators rather than multiprocessing, and it no longer freezes:

    Processor_child.py:

    ### processor_child.py ###
    import pandas as pd
    import time
    
    
    def review_with_user(var_names, dataset):
        affirmed = []
        review_message = 'Yes or no?'
    
        review_response = yield review_message
    
        if review_response in ['Yes', 'yes']:
            for v in dataset.columns:
                local_response = yield str(dataset[v].dropna())+"\n"+review_message
    
            yield affirmed
    
    if __name__ == "__main__":
        var_names = ['var1', 'var2']
        df = pd.read_csv('dummy.csv')
        gen = review_with_user(var_names, df)
        # since it is now a generator, you need yo write some code to communicate with it via the console
        # it doesn't print to the console or recieve input unless you do this manually
        while True:
            try:
                print(next(gen))
            except StopIteration:
                break
            print(gen.send(input()))
    

    Tkinter_parent.py:

    ### Tkinter_parent.py ###
    from tkinter import *
    from tkinter.filedialog import askopenfilename
    from tkinter import ttk
    import pandas as pd
    import Processor_child
    import time
    
    class GUI:
        def __init__(self, master):
            self.master = master
    
    def gui_input(message, p_review):
        def input_done(event=None):
            entry.pack_forget()
            input_label.pack_forget()
            submit_button.pack_forget()
            try:
                p_review.send(entry.get())
                next_one(p_review)
            except StopIteration:
                # this code is executed when there is no more output from Processor_child.review_with_user
                return
    
        entry = Entry(frame)
        input_label = ttk.Label(frame, text=message)
        entry.bind("", input_done)
        submit_button = ttk.Button(frame, text="Submit", command=input_done)
        input_label.pack()
        entry.pack()
        submit_button.pack()
    
    def file_select():
        dataset_path = askopenfilename()
    
        if __name__ == '__main__':
            some_vars = ['a var', 'another var']
            a_df = pd.read_csv(dataset_path)
    
            p_review = Processor_child.review_with_user(some_vars, a_df)
    
            gui_input(next(p_review), p_review)
    
    def next_one(p_review):
        try:
            gui_input(next(p_review), p_review)
        except StopIteration:
            # this code is executed when there is no more output from Processor_child.review_with_user
            return
    
    if __name__ == '__main__':
        root = Tk()
        my_gui = GUI(root)
        root.style = ttk.Style()
        root.style.configure('my.TButton')
        root.style.configure('my.TLabel')
    
        canvas = Canvas(root)
        frame = Frame(canvas)
        frame.place()
        canvas.pack(side="left", fill="both", expand=True)
        canvas.create_window((45,50), window=frame, anchor="nw")
    
        ttk.Button(frame, text="Select", command=file_select).pack()
    
        root.mainloop()
    

    Generators will throw a StopIteration exception when you call next() on them and they have finished, so be sure to put next(p_review) and and p_review.send(...) calls inside try blocks where appropriate.

提交回复
热议问题