How to send subprocess text output to a Tkinter text widget?

前端 未结 1 2016
轮回少年
轮回少年 2021-01-24 11:44
import subprocess
import os 
import time
from tkinter import *
root=Tk()
textbox=Text(root)
textbox.pack()


def redirector(inputStr):
    textbox.insert(INSERT, inputSt         


        
相关标签:
1条回答
  • 2021-01-24 12:26

    Here's something that uses multithreading that seems to do what you want. The main program is split into a portion that handles the QUI and a separate workerthread that manages the ping subprocess, collecting the results from it and putting them in a Queue whose contents periodically get transferred to the GUI.

    It uses time.sleep() because it's done in a separate thread that's not using tkinter so it's OK.

    Note, seems likely you'll might want to add a vertical scrollbar to the GUI.

    import subprocess
    import queue
    import threading
    import time
    import tkinter as tk
    
    
    class GuiPart:
        def __init__(self, master, queue, end_command):
            self.queue = queue
            self.master = master
            self.textbox = tk.Text(root)
            self.textbox.pack()
            btn = tk.Button(master, text='Quit', command=end_command)
            btn.pack(expand=True)
    
        def process_incoming(self):
            """ Handle all messages currently in the queue. """
            while self.queue.qsize():
                try:
                    info = self.queue.get_nowait()
                    self.textbox.insert(tk.INSERT, info)
                except queue.Empty:  # Shouldn't happen.
                    pass
    
    
    class ThreadedClient:
        """ Launch the main part of the GUI and the worker thread.
            periodic_call() and end_application() could reside in the GUI part, but
            putting them here keeps all the thread controls in a single place.
        """
        def __init__(self, master):
            self.master = master
            self.queue = queue.Queue()
    
            # Set up the GUI part.
            self.gui = GuiPart(master, self.queue, self.end_application)
    
            # Set up the background processing thread.
            self.running = True
            self.thread = threading.Thread(target=self.workerthread)
            self.thread.start()
    
            # Start periodic checking of the queue.
            self.periodic_call(200)
    
        def periodic_call(self, delay):
            """ Every delay ms process everything new in the queue. """
            self.gui.process_incoming()
            if not self.running:
                sys.exit(1)
            self.master.after(delay, self.periodic_call, delay)
    
        # Runs in separate thread - NO tkinter calls allowed.
        def workerthread(self):
            while self.running:
                with open('servers.txt', 'r') as file:
                    for ip in file:
                        rc = subprocess.Popen(["ping", "-c", "7", "-n", "-W", "2", ip]).wait()
                        if rc:
                            self.queue.put('ip address {} is inactive\n'.format(ip))
                        time.sleep(1)
    
        def end_application(self):
            self.running = False  # Stop queue checking.
            self.master.quit()
    
    
    if __name__ == '__main__':
        root = tk.Tk()
        root.title('Pinger')
        client = ThreadedClient(root)
        root.mainloop()  # Display application window and start tkinter event loop.
    
    0 讨论(0)
提交回复
热议问题