在不阻塞的情况下将日志记录从多个QThread编译到QTextEdit

时间:2019-07-10 14:43:05

标签: python logging qthread pyside2

Cheerio,这里的Qt新手愿意学习...

我当前正在尝试创建一个Qt应用程序,该应用程序从多个logging.Record实例中打印QThread个对象。 为此,我提出了一个最低限度的工作示例,包括带有QTextEditQPushButton的应用程序本身,自定义记录器和需要从单独的线程执行的任意长时间运行的进程。

该代码实际上可以正常工作!之所以在此发布,是因为我想听听您对如何进行增强的意见。我也希望从您那里得到一些输入,以便为此编写一个稳定的,可以正常工作的小样板。我看到人们经常遇到这个问题。

所以这是代码...

app.py

设置基本的QApplication并初始化执行QThread的{​​{1}}。

LongRunningProcess.run()

logger.py

在我看来,这有点令人费解。对于实例化此Logger的每个调用者,将创建一个import sys from PySide2 import QtCore, QtGui, QtWidgets from logger import Logger from lrp import LongRunningProcess class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.log = Logger(self._log_to_qtextedit) self.create_gui() self.thread = QtCore.QThread() self.worker = LongRunningProcess(self._log_to_qtextedit) self.thread.started.connect(self.worker.run) self.worker.moveToThread(self.thread) self.button.clicked.connect(self.run_process) def run_process(self): self.thread.start() def create_gui(self): self.centralwidget = QtWidgets.QWidget(self) layout = QtWidgets.QVBoxLayout(self.centralwidget) self.textedit = QtWidgets.QTextEdit(self) # change font of output log to monospaced font = QtGui.QFont() font.setFamily("Courier New") self.textedit.setFont(font) self.button = QtWidgets.QPushButton("push me") layout.addWidget(self.textedit) layout.addWidget(self.button) self.setLayout(layout) self.setCentralWidget(self.centralwidget) self.resize(700, 100) self.log.info("Gui initialised...") def on_application_shutdown(self): self.thread.quit() @QtCore.Slot(str) def _log_to_qtextedit(self, msg): self.textedit.append(msg) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) window = MainWindow() app.aboutToQuit.connect(window.on_application_shutdown) window.show() sys.exit(app.exec_()) 并将其传递给QueueQueueHandler连接到自定义处理程序QueueListener。每次调用处理程序的QtHandler方法时,此处理程序都会实例化QObject以便发出信号。该信号将连接到emit()传递的log_func

我还试图在每个线程之间共享队列,但是导致GUI中没有显示很多记录。

Logger

lrp.py

可以是需要一些时间才能完成的任何事情。

import logging
import sys
from logging.handlers import QueueHandler, QueueListener
from queue import Queue

from PySide2 import QtCore


class SignalEmitter(QtCore.QObject):
    request_textedit_update = QtCore.Signal(str)
    def __init__(self):
        super(SignalEmitter, self).__init__()


class QtHandler(logging.Handler):
    def __init__(self):
        super(QtHandler, self).__init__()
        self.signal_emitter = SignalEmitter()

    def emit(self, record):
        record = self.format(record)
        self.signal_emitter.request_textedit_update.emit(record)


class Logger(logging.Logger):
    def __init__(self, log_func, level=logging.DEBUG, name="root"):
        super(Logger, self).__init__(name)
        queue = Queue()
        self.setLevel(level)
        self.handlers_ = {
            "queue_handler": QueueHandler(queue),
            "console_handler": logging.StreamHandler()
        }
        formatter = logging.Formatter("%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
        for handler in self.handlers_.values():
            print(handler)
            handler.setFormatter(formatter)
            self.addHandler(handler)

        qthandler = QtHandler()
        qthandler.signal_emitter.request_textedit_update.connect(log_func)
        qthandler.setFormatter(formatter)
        self.listener = QueueListener(
            queue, qthandler
        )
        self.listener.start()

    def stop_listening(self):
        self.listener.stop()

0 个答案:

没有答案