Qt Designer displaying in real time the output of a python script

Question:

I have a few issues with an application I’m trying to write so I’ll start by giving a sort of a “big picture” description of all the interactions:

I have a simple UI written in Qt Designer. This launches a series of python scripts which do different kind of manipulations on some files. The user is informed by all the actions via print, but this happens in command line.
So far all works as needed/intended.

IMPORTANT: sometimes a user input is needed: either value or just “press any key” type of thing. Again, works as intended in cmd line.

Now what I want to do is to add all the information that comes up from the python scripts in cmd line to the Qt Designer UI.

What works:
I’m able to get output of the python execution and to display it in a textEdit object

What doesn’t work:
the UI is only updated at the end of the execution and is not responding while the script execution is ongoing

I would like to have the ui updated line by line as text comes in and not as batch.

how I do it:

class my_ui(QtWidgets.QMainWindow):
    ...
    def button_pressed
         self.__process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
         while self.__process.poll() is None:
            line = self.__process.stdout.readline() 
            print(line)

    def main(self):
        ...
        self.console_output_to_ui()

    def write(self, text):
       self.ui.textEdit.append(text)

    def console_output_to_ui(self):
       sys.stdout = self

now the output I grab looks like this:

....
b"evaluate_condition(): '4'rn"
# time delay 1s
b"evaluate_condition(): '5'rn"
# time delay 1s
b"evaluate_condition(): '6'rn"
....

Ignoring the bad formatting for now, I would like to

  1. have this log displayed line by line just as is in cmd/debug in python in the Qt Designer UI in real time without blocking/locking the UI.

  2. find a way to pass a parameter/input value to the executing process.I think I might need the stdin defined too , but how to pass it from QtDesigner to the process is something I could not figure out.

Thanks!

Asked By: papa bear

||

Answers:

well, for anyone looking around here the first problem is solved.
How:

removed the sys.stdout highjack and replaced it with a thread write(deleted also write function that’s not needed, same with console_output_to_ui and its call):

self.__process = subprocess.Popen(cmd, stdout=PIPE,  universal_newlines=True, shell=False)
t = Thread(target=self.thread_read)
t.start()


def thread_read(self):
    while self.__process.poll() is None:
        line = self.__process.stdout.readline()
        temp = line.lstrip()
        temp = temp.replace("n", "")
        # don't print empty lines
        if len(temp) > 1:
            self.ui.textEdit.append(temp)

this way in the ui textEdit I hav a log that looks like this:

evaluate_condition(): '6'
evaluate_condition(): '7'
evaluate_condition(): '8'
evaluate_condition(): '9'

and it’s updated line by line just as the cmd window output.

Now working on a solution for problem no.2

Answered By: papa bear

second problem fixed.

process.stdin.write(my_input_data + 'n')
process.stdin.flush()

this sends it to the subprocess.

In the end though the reading from subprocess and the udpate from UI was done in a thread. A lot more elegant and safe.
If anyone wants to know exactly how, just ask, I can add more code examples.

Answered By: papa bear

My UI doesn’t update the log until I add self.textEdit.setReadOnly(True).

Answered By: KaiTheUser