I have to call a legacy Bash program and output the results to a Qt window. The problem is the subprocess the Bash command is executed in doesn’t return each output line as they happen; the subprocess waits until the entire Bash command is finished, then it dumps everything to the window. Thus, if the Bash command takes a long time, the user may think the system is frozen.
I can get the subprocess to print each line via a print(output.readlin()) to a normal terminal. But I can’t do it within Qt. I have tried a number of different examples and either they don’t work or continue to dump the results at the end of the process.
I don’t know if this a problem that an unknown Qt module might help me with or if it’s just something with how Python deals w/ subprocess calls to Bash commands, like it’s running a batch job and only returning results once the batch is done.
Here is the trouble code I’m working with:
self.console = OutputConsole()
out = subprocess.run(["bash", "-c", f"source path_to_setup_file -r && cd parent_directory && build_project_command"], stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
self.console.on_update_text(out.stdout.decode())
class OutputConsole(QWidget):
"""Collects output data (sys.stdout) from subprocess calls to ocpidev. Prints the output to the console view."""
process: QTextEdit
def __init__(self, process: QTextEdit) -> None:
"""Create the process that manages text editing on the console"""
super().__init__()
sys.stdout = Stream()
self.process = process
self.process.moveCursor(QTextCursor.Start)
self.process.ensureCursorVisible()
self.process.setLineWrapColumnOrWidth(1000)
self.process.setLineWrapMode(QTextEdit.FixedPixelWidth)
def on_update_text(self, text: str) -> None:
"""Add new text to the console as stdout gets more data"""
cursor: QTextCursor = self.process.textCursor()
cursor.movePosition(QTextCursor.End)
cursor.insertText(text)
self.process.setTextCursor(cursor)
self.process.ensureCursorVisible()
def __del__(self) -> None:
"""Reset sys.stdout to normal functionality"""
sys.stdout = sys.__stdout__