子进程的Python Tkinter stdout重定向不打印到GUI小部件(需要协助)

时间:2017-06-02 21:57:17

标签: tkinter python-3.5 python-multiprocessing

目前我正在运行Python 3.5。

我的文件基本上有两个GUI窗口......第一个请求输入,在提交输入后,第二个出现在函数执行时。在此期间,此函数在与GUI不同的线程中运行。

此外,该线程使用multiprocessing.pool命令调用一个函数,该命令调用另一个函数来多次执行相同的任务。

不幸的是,所有stdout输出都被发送到控制台而不是我的第二个GUI的Text Widget(第一个GUI工作,因为我使用stdout重定向器类)。我尝试了两个不同版本的代码来尝试解决这个问题......一个是将我的函数内部放到GUI中,另一个是将它们放在外面。

当它们内部存在于GUI时,重定向器工作......但是然后进程不会运行多个实例,一次只运行一个(我假设是由于仅使用一个线程,不确定)。

当保持多个进程外部的函数运行时,一切正常,但是正在运行的子进程的输出(如前所述,它们只是输出到控制台)。

非常感谢任何帮助。

以下是相关代码的片段:

class StdoutRedirector(object):
  def __init__(self,text_widget):
    self.text_space = text_widget
  def write(self,string):
    self.text_space.insert('end', string)
    self.text_space.see('end')
  def flush(self):
    pass

class OutputWindowGUI:
  def __init__(self, root):
    self.root = root
    root.wm_title("GUI")
    self.label = Label(root, text="Output:", font=24).grid(row=0, column=2, columnspan=2)
    self.root.geometry("650x600")
    self.root.lift()
    self.root.attributes('-topmost',True)
    self.root.after_idle(root.attributes,'-topmost',False)

    self.textBoxFrame = tkinter.Frame(root)
    self.textBoxFrame.grid(row=5, column=3, columnspan=1, sticky=E+W)

    self.textbox=Text(self.textBoxFrame)
    self.textbox=Text(wrap=WORD)
    self.textbox.grid(row=5, column=3, sticky=W, pady=2)


    sys.stdout = StdoutRedirector(self.textbox)
    sys.stdin = StdoutRedirector(self.textbox)
    sys.stderr = StdoutRedirector(self.textbox)

    self.buttonFrameClose = tkinter.Frame(root)
    self.buttonFrameClose.grid(row=6, column=3)
    self.buttonFrame = tkinter.Frame(root)
    self.buttonFrame.grid(row=2, column=2, columnspan=3)
    self.close_all_button = Button(self.buttonFrameClose, text='Close App', command=self.close_all, height = 3, width = 15).grid(row=2, column=1, sticky=W, pady=4)

    self.gui_thread = threading.Thread(target = apply_async_with_callback)
    self.gui_thread.start()


  def close_all(self):
    self.root.destroy()
    sys.exit(1)



def start_commands(a_device, vpntermination):
  time.sleep(.1)
  try:
    net_connect = ConnectHandler(**a_device)
    hostname = net_connect.send_command("show hostname") #Used to store Hostname.
    output = net_connect.send_command("vpn-sessiondb logoff name " + str(vpntermination) +  " noconfirm") #Used for vpn termination command.
    print('\n******* Output for device ' + hostname + ' *******' )
    print(output)
    print('')
    net_connect.disconnect() 
  except (NetMikoTimeoutException, NetMikoAuthenticationException) as e: #Handles timeout errors.
    print("Could not connect to " + a_device.get("ip") + ", Error: ", e)
    print('')

def apply_async_with_callback():
  start_time = datetime.now()

  with Pool(processes=3) as pool:
    results = [pool.apply_async(start_commands, args = (a_device, vpntermination)) for a_device in all_firewalls]

    pool.close()
    pool.join()

  end_time = datetime.now() 
  total_time = end_time - start_time 
  print('\nTotal process time: ' + str(total_time))

def main():
  credentials()

  master = Tk()
  my_gui = InputWindowGUI(master)
  master.mainloop()

  root=Tk()
  out_gui = OutputWindowGUI(root)
  root.mainloop() 

if __name__=='__main__':
  freeze_support()
  main()  

0 个答案:

没有答案