Reputation: 143
I am writing a python app to take some inputs from the user and call a shell script based on these inputs.
This shell script can run for quite sometime, and I want to redirect the output it produces (in realtime) to tkinter. I managed to do that, but it only happens after the shell script is completely finished, not as soon as the shell script "echos" something for example.
So main problem: 1. Output appears in the text widget only after shellScript.sh is exited (although if I run the same in the terminal manually, I see continuous output). 2. Side problem: all the "\n" printed in the output are just printed as "\n" and no new lines are added in the text widget.
here is what I have:
class RedirectText(object):
def __init__(self, text_ctrl):
"""Constructor"""
self.output = text_ctrl
def write(self, string):
self.output.insert(tk.END, string[2:])
class Gui(GuiApp):
def __init__(self, master=None):
redir = RedirectText(self.text_Output)
sys.stdout = redir
def testRun(self, event=None):
p = subprocess.Popen(["./shellScript.sh"], stdout=subprocess.PIPE)
print(p.communicate()[0])
Upvotes: 3
Views: 1239
Reputation: 47219
As p.communicate()
will wait for the process to complete, so use p.poll()
and p.stdout.readline()
instead. Also put the process in a thread to avoid blocking the main thread:
import threading
...
class Gui(GuiApp):
...
def runScript(self):
print('started')
p = subprocess.Popen(['./shellScript.sh'], stdout=subprocess.PIPE, bufsize=1, text=True)
while p.poll() is None: # check whether process is still running
msg = p.stdout.readline().strip() # read a line from the process output
if msg:
print(msg)
print('finished')
def testRun(self, event=None):
# create a thread to run the script
threading.Thread(target=self.runScript, daemon=True).start()
Upvotes: 1