0

我有兩個腳本:如何在Tkinter父級腳本中實現`input`方法,並將顯示的提示和返回值發送回子腳本?

Processor_child.py:其目的是執行一些數據分析和清理操作。當單獨運行時(不包括Tkinter_parent.py),它必須執行與使用Tkinter_parent.py打包到GUI中時相同的操作。

Tkinter_parent.py:它的目的是爲那些無法直接使用Processor_child的用戶提供GUI。

當我掙扎是從重現蟒蛇input功能Processor_child.py在這兩個一起使用的GUI的實例。我需要向用戶提供一個提示(在下面的代碼中完成),將該響應傳遞給GUI(可用於此的各種選項,例如Pipe),並且只有在響應已通過後,Processor_child才能恢復其操作/檢索入門價值(如何?)。該問題的

實施例的代碼,用###註釋###表示在需要插入以執行期望的功能的代碼:

### Processor_child.py ### 
import pandas as pd 

def smart_print(message, a_pipe = None): 
    if __name__ == "__main__": 
     print(message) 
    else: 
     a_pipe.send(message) 

def review_with_user(var_names, dataset, a_pipe = None): 
    affirmed = [] 
    review_message = 'Yes or no?' 

    if __name__ == "__main__": 
     review_response = input(review_message) 
    else: 
     smart_print(review_message, a_pipe) 
     review_response = 'Yes' ### INSTEAD SOMEHOW GET RESPONSE FROM Tkinter_parent.py ### 

    if review_response in ['Yes', 'yes']: 
     for v in set(var_names): 
      smart_print(dataset[v].dropna()[:8], a_pipe) 
      if __name__ == "__main__": 
       local_response = input(review_message) 
      else: 
       local_response = None ### INSTEAD SOMEHOW GET RESPONSE FROM Tkinter_parent.py ### 
      if local_response in ['Yes', 'yes']: 
       affirmed.append(v) 

if __name__ == "__main__": 
    var_names = ['var1', 'var2'] 
    df = pd.read_csv('dummy.csv') 
    review_with_user(var_names, df) 

而且Tkinter_parent.py:

### Tkinter_parent.py ### 
from tkinter import * 
from tkinter.filedialog import askopenfilename 
from tkinter import ttk 
from multiprocessing import Process, Pipe 
import pandas as pd 
import Processor_child 

class GUI: 
    def __init__(self, master): 
     self.master = master 

def gui_input(message): 
    def input_done(event=None): 
     ### INSTEAD SOMEHOW send entry.get() back to Processor_child.py ### 
     pass 

    entry = Entry(frame) 
    input_label = ttk.Label(frame, text=message) 
    entry.bind("<Return>", 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__': 
     pipe1, pipe2 = Pipe() 

     some_vars = ['a var', 'another var'] 
     a_df = pd.read_csv(dataset_path) 

     p_review = Process(target=Processor_child.review_with_user, args=(some_vars, a_df, pipe2)) 
     p_review.start() 

     gui_input(pipe1.recv()) 

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() 

我我們已經回顧了SO上的一些相關問題,如 Getting a TKinter input stored into a string variable in the next function?:但它們不適用於在執行其他操作之前等待輸入的情況(如我在此處介紹的兩種情況)。

其他SO問題如How do I make the program wait for an input using an Entry box in Python GUI?在這些情況下不起作用,其中嵌入在另一個腳本的執行功能內的循環內的輸入;他們依靠在GUI腳本本身內完成的「等待」。

回答

0

注意:這隻適用於極少數情況。這不是一個真正的「解決方案」......我仍然面臨這個問題。固定方法如下都有自己的SO問題:Tkinter application 'freezes' while continually polling Pipe for contents (multiprocessing)


我已經能夠找到一個僞解決方案我在其中添加while循環,即pollPipe,並在發現該Pipe確實包含內容,請求Pipe中的數據。這些while循環很容易使應用程序超載,而且似乎只能用於簡化的情況。絕對不是最好的方法。

見修改代碼:

### processor_child.py ### 
import pandas as pd 
from multiprocessing import * 
import time 

def smart_print(message, a_pipe = None): 
    if __name__ == "__main__": 
     print(message) 
    else: 
     a_pipe.send(message) 

def review_with_user(var_names, dataset, a_pipe = None): 
    affirmed = [] 
    review_message = 'Yes or no?' 

    if __name__ == "__main__": 
     review_response = input(review_message) 
    else: 
     smart_print(review_message, a_pipe) 
     while a_pipe.poll() != True: 
      time.sleep(0.1) 

     review_response = a_pipe.recv() 

    if review_response in ['Yes', 'yes']: 
     for v in dataset.columns: 
      smart_print(dataset[v].dropna(), a_pipe) 
      if __name__ == "__main__": 
       local_response = input(review_message) 
      else: 
       while a_pipe.poll() != True: 
        time.sleep(0.1) 
       local_response = a_pipe.recv() 
      if local_response in ['Yes', 'yes']: 
       affirmed.append(v) 

     smart_print(affirmed, a_pipe) 

if __name__ == "__main__": 
    var_names = ['var1', 'var2'] 
    df = pd.read_csv('dummy.csv') 
    review_with_user(var_names, df) 

而且Tkinter_parent.py:

### Tkinter_parent.py ### 
from tkinter import * 
from tkinter.filedialog import askopenfilename 
from tkinter import ttk 
from multiprocessing import Process, Pipe 
import pandas as pd 
import Processor_child 
import time 

class GUI: 
    def __init__(self, master): 
     self.master = master 

def gui_input(message, a_pipe = None): 
    def input_done(event=None): 
     entry.pack_forget() 
     input_label.pack_forget() 
     submit_button.pack_forget() 
     a_pipe.send(entry.get()) 
     next_one(a_pipe) 

    entry = Entry(frame) 
    input_label = ttk.Label(frame, text=message) 
    entry.bind("<Return>", 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__': 
     pipe1, pipe2 = Pipe() 

     some_vars = ['a var', 'another var'] 
     a_df = pd.read_csv(dataset_path) 

     p_review = Process(target=Processor_child.review_with_user, args=(some_vars, a_df, pipe2)) 
     p_review.start() 

     gui_input(pipe1.recv(), pipe1) 

     #time.sleep(1) 
def next_one(pipe1): 
    while pipe1.poll() != True: 
     time.sleep(0.1) 

    gui_input(pipe1.recv(), pipe1) 

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() 
+0

與multiprocessing.connection.wait()類似的解決方案有相同的問題,可能是因爲不支持的方法Windows(我正在開發Windows機器,Windows機器)。 – user1318135