PySide6 GUI 编程(47): 基于QProcess运行外部命令

2024-09-18 13:40:46 浏览数 (1)

关于 QProcess

QProcess 可以用来启动外部程序。这在需要从 Qt 应用中运行第三方工具或命令行程序时非常有用。例如,一个图形用户界面(GUI)应用可能需要调用一个命令行工具来处理数据或执行某些操作。

通过 QProcess,你可以捕获并处理外部程序的标准输出和标准错误输出。这对于显示外部程序的状态、结果或进行错误处理非常重要。例如,如果你的应用依赖于某个外部脚本的结果,你可以通过 QProcess 来执行这个脚本并实时获取输出。

QProcess 也可以向运行的外部程序发送输入。这在需要与启动的进程进行交互式通信时非常有用。例如,你可以从 GUI 接收用户输入,并将这些输入发送到一个交互式命令行程序。

在需要并行处理任务而不阻塞主用户界面线程的情况下,QProcess 可以用来在后台运行重量级任务。这样,GUI 保持响应,同时后台进程处理复杂或耗时的任务。

示例代码

构造 python 交互式运行环境

代码语言:python代码运行次数:0复制
from __future__ import annotations

import sys

from PySide6.QtCore import QProcess
from PySide6.QtWidgets import QApplication, QLineEdit, QMainWindow, QPushButton, QTextEdit, QVBoxLayout, QWidget


class InteractiveREPL(QMainWindow):
    def __init__(self):
        super().__init__()
        self.output_text = QTextEdit(self)
        self.input_line = QLineEdit(self)
        self.send_button = QPushButton("Send", self)
        self.process = QProcess(self)  # 创建 QProcess 对象
        self.init_ui()
        self.setup_connections()

    def init_ui(self):
        self.setWindowTitle("Interactive Python REPL Based on PySide6 QProcess")

        # 创建布局和控件
        self.output_text.setReadOnly(True)

        layout = QVBoxLayout()
        layout.addWidget(self.output_text)
        layout.addWidget(self.input_line)
        layout.addWidget(self.send_button)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def setup_connections(self):
        # 连接按钮点击事件和处理函数
        self.send_button.clicked.connect(self.send_input)
        # 连接 QProcess 的输出信号到槽函数
        self.process.readyReadStandardOutput.connect(self.handle_output)
        self.process.readyReadStandardError.connect(self.handle_output)

    def start_repl(self):
        # 启动 Python REPL
        self.process.start("python3", ["-i"])  # '-i' 选项启动交互模式
        self.output_text.append("REPL started...n")

    def send_input(self):
        # 获取输入并发送到进程
        text = self.input_line.text()
        if text.strip():  # 确保不是空行
            output_str = ">>> "   text
            print('input echo:', output_str)
            self.output_text.append(output_str)  # 手动回显输入
        self.process.write((text   'n').encode())  # 写入必须是 bytes
        self.input_line.clear()

    def handle_output(self):
        # 读取进程输出并显示
        data = self.process.readAllStandardOutput()
        resp_str = data.data().decode()
        if len(resp_str) > 0:
            print('resp str:', resp_str)
            self.output_text.append(resp_str)
            return

        # 读取进程错误输出并显示
        stderr = self.process.readAllStandardError()
        resp_err_str = stderr.data().decode()
        if stderr:
            # 如果输出是 '>>> ' 则认为是 REPL 的输出
            if resp_err_str == '>>> ':
                return
            print('resp err:', resp_err_str)
            self.output_text.append(resp_err_str)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = InteractiveREPL()
    window.show()
    window.start_repl()  # 启动 REPL
    sys.exit(app.exec())

运行效果

界面效果界面效果
交互效果交互效果

0 人点赞