Qt Designer 实时显示 python 脚本的输出

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

我尝试编写的应用程序存在一些问题,因此我将首先对所有交互进行某种 "big picture" 描述:

我有一个用 Qt Designer 编写的简单 UI。这将启动一系列 python 脚本,这些脚本对某些文件进行不同类型的操作。通过打印通知用户所有操作,但这发生在命令行中。 到目前为止,所有作品都是 needed/intended.

重要提示:有时需要用户输入:值或只是 "press any key" 类型的东西。同样,在 cmd 行中按预期工作。

现在我要做的是将 cmd 行中 python 脚本产生的所有信息添加到 Qt Designer UI。

什么有效: 我能够获得 python 执行的输出并将其显示在文本编辑对象

什么不起作用: UI 仅在执行结束时更新,并且在脚本执行过程中没有响应

我希望 ui 在文本输入时逐行更新,而不是批量更新。

我是怎么做到的:

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

现在我抓取的输出如下所示:

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

暂时忽略格式错误,我想

  1. 在 Qt Designer UI 中实时逐行显示此日志,就像在 cmd/debug 中 python 中一样,而无需 blocking/locking UI.

  2. 找到一种方法将 parameter/input 值传递给正在执行的 process.I 认为我可能也需要定义标准输入,但是如何将它从 QtDesigner 传递到进程是我想不通的事情。

谢谢!

嗯,对于任何环顾四周的人来说,第一个问题已经解决了。 如何:

删除了 sys.stdout highjack 并将其替换为线程写入(删除了不需要的写入函数,与 console_output_to_ui 及其调用相同):

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)

这种方式在 ui textEdit 中我有一个看起来像这样的日志:

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

并且它是逐行更新的,就像 cmd window 输出一样。

正在研究问题 2 的解决方案

第二个问题已解决。

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

这会将它发送到子进程。

最后虽然从子进程读取和从 UI 更新是在一个线程中完成的。更加优雅和安全。 如果有人想知道具体如何,尽管问,我可以添加更多代码示例。