You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中如何在子线程更新文件时实时读取内容并更新绘图

问题根因与修复方案

核心错误是多线程绑定信号槽的写法错误,导致长耗时任务实际还是在主线程执行,阻塞了UI和文件监听事件。

1. 核心错误:信号槽连接时直接执行了任务方法

你在runLongTask中写的self.thread.started.connect(self.worker.run(param1,param2)),这里加了括号调用run()方法,会在绑定信号的瞬间就直接在主线程执行该方法,根本没有等到子线程启动,所以会卡住整个界面,直到方法执行完才会继续响应后续事件。
修复方式:用lambda表达式包裹带参数的方法调用,保证子线程启动时才执行任务:

# 错误写法,会立即执行run方法
# self.thread.started.connect(self.worker.run(param1,param2))
# 正确写法
self.thread.started.connect(lambda: self.worker.run(param1, param2))

2. 其他需要修复的小问题

  • 代码中没有实现startSliceScan方法,点击按钮不会触发任务执行,需要补充该方法调用runLongTask
  • update_graph方法中引用了不存在的self.path,替换为你定义的self.filePath
  • 多次触发任务时可能存在线程、监听器重复绑定的问题,建议执行任务前先禁用开始按钮,任务结束后再恢复

修复后完整可运行的核心代码参考

from PyQt5 import QtWidgets, uic, QtCore, QtGui
from pyqtgraph import PlotWidget
from PyQt5.QtCore import QObject, QThread, pyqtSignal
import pyqtgraph as pg
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog, QMainWindow
import os
from os.path import exists
import csv
import numpy as np
import pandas as pd

import myModule

dirname = os.path.dirname(__file__)
class Worker(QObject):
    finished = pyqtSignal()

    def run(self,param1,param2):
        """Long-running task with user input from terminal."""
        myModule.userInputFunction(param1,param2)
        self.finished.emit()

class someWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(someWindow, self).__init__(*args, **kwargs)
        uic.loadUi('somewindow.ui', self)
        self.directoryPath = "data"
        # 保证data目录存在,避免监听失败
        os.makedirs(self.directoryPath, exist_ok=True)
        self.fs_watcher = QtCore.QFileSystemWatcher()
        self.fs_watcher.addPath(self.directoryPath)
        self.fs_watcher.directoryChanged.connect(self.dataFileCreated)
        self.StartScanButton.clicked.connect(self.startSliceScan)
        self.EndScanButton.clicked.connect(self.endScan)
        # 初始化线程相关变量
        self.thread = None
        self.worker = None

    def dataFileCreated(self):
        self.filePath = os.path.join(dirname, "data/"+ self.runNameBox.toPlainText()+"_Rec.txt")
        print(self.filePath + " dataFileCreated")
        # 避免重复添加路径
        if self.filePath not in self.fs_watcher.files():
            self.fs_watcher.addPath(self.filePath)
            self.fs_watcher.fileChanged.connect(self.update_graph)

    def update_graph(self):
        if exists(self.filePath):
            print("file exists!")
            # 读取文件最新行绘图的逻辑写在这里
        else:
            print("file doesn't exist yet")

    def endScan(self):
        # 结束任务时手动终止线程
        if self.thread and self.thread.isRunning():
            self.thread.quit()
            self.thread.wait()
        self.StartScanButton.setDisabled(False)

    def startSliceScan(self):
        # 任务开始前禁用按钮,避免重复触发
        self.StartScanButton.setDisabled(True)
        # 这里替换为你实际要传的param1、param2参数
        param1 = "你的参数1"
        param2 = "你的参数2"
        self.runLongTask(param1, param2)

    def runLongTask(self, param1, param2):
        # 先清理旧的线程对象
        if self.thread is not None and self.thread.isRunning():
            self.thread.quit()
            self.thread.wait()
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        # 用lambda传递参数,保证run方法在子线程执行
        self.thread.started.connect(lambda: self.worker.run(param1, param2))
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        # 任务结束后恢复按钮
        self.thread.finished.connect(lambda: self.StartScanButton.setDisabled(False))
        self.thread.start()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = someWindow()
    w.show()
    sys.exit(app.exec_())

额外注意事项

  • 如果myModule.userInputFunction内部有大量非常频繁的文件写入关闭操作,可能会导致QFileSystemWatcher触发延迟,可以搭配一个100ms左右的QTimer做补充校验,避免漏更
  • 终端输入操作不会影响子线程运行,完全不会阻塞主线程的UI更新和文件监听逻辑

内容的提问来源于stack exchange,提问作者Bubbles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 17:06:04