Pyside6常用的三种进程(线程)的介绍

1.QProcess的介绍   

一、QProcess 核心功能

QProcess 是 Qt 框架中用于启动外部程序并与其交互的核心类。主要功能包括:

  1. 进程启动与控制:支持同步(execute())和异步(start())执行外部程序。
  2. 进程通信:通过标准输入(stdin)、输出(stdout)和错误输出(stderr)通道与子进程交互。
  3. 状态监控:通过信号(如 started()、finished())实时跟踪进程状态。
  4. 资源管理:提供 kill() 和 terminate() 强制终止进程,并支持自动释放资源
二、基本使用步骤
1. 启动外部程序

需明确指定程序路径和参数,避免直接传递完整命令字符串(旧版已弃用):

from PySide6.QtCore import QProcess
 
process = QProcess()
process.setProgram("python3")  # 设置程序路径
process.setArguments(["-i"])   # 设置参数(如交互模式)
process.start()                # 启动进程

⚠️ 注意:旧版 start("python dummy.py") 已弃用,需分离程序名和参数 。

2. 处理输入输出

通过信号与槽机制实现异步通信,避免阻塞主线程:

# 连接输出信号到处理函数
process.readyReadStandardOutput.connect(handle_stdout)
process.readyReadStandardError.connect(handle_stderr)
 
def handle_stdout():
    data = process.readAllStandardOutput()
    print("标准输出:", data.data().decode())
 
def handle_stderr():
    data = process.readAllStandardError()
    print("错误输出:", data.data().decode())
3. 进程状态监控
  • 信号绑定:监听进程启动、结束和错误事件:

process.started.connect(lambda: print("进程已启动"))
process.finished.connect(lambda: print("进程结束,退出码:", process.exitCode()))
process.errorOccurred.connect(lambda err: print("错误发生:", err))
  • 状态查询:通过 state() 获取当前状态(QProcess.NotRunningQProcess.Running)。

4. 进程终止与资源释放
  • 强制终止

    • terminate():发送终止信号(允许进程清理资源)。
    • kill():立即终止进程(可能残留资源)。
if process.state() == QProcess.Running:
    process.terminate()
    process.waitForFinished(3000)  # 最多等待3秒
  •  自动释放:通过 deleteLater() 延迟删除对象:
process.finished.connect(process.deleteLater)

2.QThread的介绍      

一、基础概念

        QThread 是 Qt 提供的跨平台线程管理类,用于将耗时任务从主线程(GUI 线程)中分离,避免界面卡顿。其核心功能包括线程创建、任务执行、线程间通信及资源管理。

二、两种使用模式
 1. 子类化 QThread(重写 run() 方法)

适用场景:任务逻辑简单且独立,无需频繁交互。
实现步骤:

from PySide6.QtCore import QThread, Signal

class WorkerThread(QThread):
    finished = Signal(str)  # 自定义信号

    def run(self):
        result = "Task completed"  # 耗时操作
        self.finished.emit(result)  # 发射信号

# 使用示例
thread = WorkerThread()
thread.finished.connect(handle_result)  # 连接信号到处理函数
thread.start()  # 启动线程

 特点
        线程逻辑直接封装在 run() 中。
        线程结束后需调用 quit() 和 wait() 释放资源


2. 使用 moveToThread(推荐模式)
       

        适用场景:任务复杂、需与主线程频繁交互或需要灵活控制生命周期。
        实现步骤:

from PySide6.QtCore import QObject, QThread, Signal

class Worker(QObject):
    finished = Signal(str)

    def do_work(self):
        result = "Task completed"  # 耗时操作
        self.finished.emit(result)

# 创建对象和线程
worker = Worker()
thread = QThread()
worker.moveToThread(thread)  # 将任务对象移入子线程

# 信号与槽连接
thread.started.connect(worker.do_work)
worker.finished.connect(thread.quit)  # 完成后退出线程
worker.finished.connect(worker.deleteLater)  # 释放资源
thread.finished.connect(thread.deleteLater)

thread.start()  # 启动线程

 特点:
        任务逻辑与线程管理分离,代码更清晰。
        通过信号槽机制实现线程间安全通信,避免直接操作 GUI

三、信号与槽机制

核心信号
        started:线程启动时发射。
        finished:线程结束时发射。
自定义信号(如进度更新、结果返回等)
跨线程通信示例:

class Worker(QObject):
    progress = Signal(int)
    finished = Signal(str)

    def long_task(self):
        for i in range(100):
            time.sleep(0.1)
            self.progress.emit(i + 1)  # 发射进度信号
        self.finished.emit("Completed")

# 主线程连接信号
worker.progress.connect(update_progress_bar)
worker.finished.connect(show_result)
四、生命周期管理

线程的完整生命周期包括创建、启动、运行、等待、完成和销毁六个阶段:

创建:实例化 QThread 和任务对象。
启动:调用 start() 进入运行状态。
运行:执行 run() 或绑定的任务函数。
等待:通过 wait() 阻塞主线程直到子线程结束。
完成:发射 finished 信号。
销毁:
        调用 quit() 退出线程。
        调用 wait() 确保资源释放。
        使用 deleteLater() 延迟删除对象 。
以下是一个简单的 QThread 示例,展示了如何通过子类化 QThread 来管理线程生命周期:

from PySide6.QtCore import QThread, Signal
import time

class WorkerThread(QThread):
    finished = Signal(str)  # 自定义信号,用于传递任务完成信息

    def run(self):
        # 模拟耗时操作
        for i in range(5):
            print(f"Worker thread is running: {i}")
            time.sleep(1)
        self.finished.emit("Task completed")  # 发射信号,表示任务完成

# 创建并启动线程
thread = WorkerThread()
thread.finished.connect(lambda msg: print(f"Thread finished: {msg}"))
thread.finished.connect(thread.deleteLater)  # 线程完成后自动销毁
thread.start()

# 阻塞主线程,等待子线程完成
thread.wait()
print("Main thread continues after thread completion")

示例说明
        创建线程:通过继承 QThread,定义 WorkerThread 类,并在 run() 方法中模拟耗时任务。
        启动线程:调用 thread.start() 启动线程。
        线程运行:run() 方法中执行任务,并通过 time.sleep(1) 模拟耗时操作。
        线程完成:任务完成后,通过 finished.emit() 发射信号。
        销毁线程:finished.connect(thread.deleteLater) 确保线程完成后自动销毁

3. subprocess的使用说明

         subprocess 是 Python 用于执行外部命令和进程管理的核心模块,提供了更灵活的子进程控制方式。

一、subprocess.Popen最底层的进程创建方式,支持实时交互   

subprocess模块定义了一个类: Popen,具体如下所示:Pyside6常用的三种进程(线程)的介绍_第1张图片
class subprocess.Popen( args,bufsize=0,
executable=None,
stdin=None,
stdout=None,
stderr=None,
preexec_fn=None,
close_fds=False,
shell=False,
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0) 

下面我将重点介绍一下stdin stdout和stderr:

        stdin stdout和stderr,分别表示子程序的标准输入、标准输出和标准错误。可选的值有PIPE或者一个有效的文件描述符(其实是个正整数)或者一个文件对象,还有None。如果是PIPE,则表示需要创建一个新的管道,如果是None,不会做任何重定向工作,子进程的文件描述符会继承父进程的。另外,stderr的值还可以是STDOUT,表示子进程的标准错误也输出到标准输出。

可以通过下面的代码实现实时读取输出:用到了stdout 

while True:
    output = process.stdout.readline()
    if not output and process.poll() is not None:
        break
    print(output.strip())

 通过下面的代码实现错误处理

try:
    subprocess.check_call(["invalid_command"])  # 非零退出码时抛异常
except subprocess.CalledProcessError as e:
    print(f"Error: {e}")
二、subprocess.run(推荐):简化版,自动等待命令完成。

 使用 subprocess 运行 Python 脚本并捕获错误:

try:
    result = subprocess.run(
        ["python", "train.py"], 
        check=True, 
        capture_output=True, 
        text=True
    )
except subprocess.CalledProcessError as e:
    print(f"训练失败: {e.stderr}")

下面是上述三种方法的对比说明: 

 Pyside6常用的三种进程(线程)的介绍_第2张图片

你可能感兴趣的:(python,开发语言)