-1

My tkinter GUI (python 2.7) starts a subprocess that can run for quite a while and I use PIPE to send print statements to a text widget. It can run for a long time w/o any print statements and the GUI window says "Not responding" and I can do nothing in that window.

#lauch main
proc = subprocess.Popen(["python", testPath, filePath] + script_list,
                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)

#send the scripts output to the GUI text box
for line in iter(proc.stdout.readline,''):
    text.insert(END, line)
    #update in "real time"
    text.see(END)
    root.update()
    text.update_idletasks()

Tried adding print and flush statements in the subprocess but that does not help.

martineau
  • 119,623
  • 25
  • 170
  • 301
MarkB
  • 7
  • 2

1 Answers1

0

Does this below example give you a method to read the output from subprocess?

import threading
from tkinter import  *
import subprocess
import time

class SubprocessThread(threading.Thread):
    def __init__(self, widget):
        threading.Thread.__init__(self)
        self.widget = widget
        self.stopEvent = threading.Event()
        print("Task Initialised")
    def run(self):
        print("Task Running")
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        proc = subprocess.Popen(["ping", "-n", "8", "8.8.8.8"],
                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, startupinfo=startupinfo)
        
        for line in iter(proc.stdout.readline,''):
            if self.stopEvent.is_set():
                break
            self.widget.insert('end',line.decode())
            time.sleep(0.1)
        self.widget.insert('end',"\n\nComplete")



def startTask():
    task.start()

def stopTask():
    task.stopEvent.set()
            
        
gui = Tk()

text = Text(gui,width=80)
text.pack()


button1 = Button(gui, text='Start Process', fg='white', bg='gray', height=2, width=9, command=startTask)
button1.pack()

button2 = Button(gui, text='Stop Process', fg='white', bg='gray', height=2, width=9, command=stopTask)
button2.pack()



# start the GUI
task = SubprocessThread(text)

gui.mainloop()

This creates a separate thread that will 'listen' out for new stdout from the called process. In this example I just call ping.

Just a note, it is usually bad practice to call another python script using subprocess. Why not just call the functions inside that script.

scotty3785
  • 6,763
  • 1
  • 25
  • 35