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

PyQt日志配置:如何让QTextEdit仅接收DEBUG级日志?

日志分级输出配置问题:QTextEdit仅接收DEBUG级日志

我开发了一个带日志文本区域的小型GUI应用,需要实现以下日志分级输出需求:

  • 将DEBUG级日志输出到QTextEdit组件
  • 将ERROR级日志写入文件

目前ERROR级日志已成功过滤并写入文件,但QTextEdit会捕获所有级别的日志,请问如何配置才能让QTextEdit仅接收DEBUG级日志?

现有代码

main.py

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebSockets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from dashboard import MainApp
import logging
from dotenv import load_dotenv
import os

def setup_logging():
    logging.basicConfig(
        level = logging.DEBUG, 
        format = '[%(asctime)s] %(levelname)s - %(message)s',
        datefmt ='%H:%M:%S'          
    )

    logger = logging.getLogger("mylog")
    formatter = logging.Formatter(
        '%(asctime)s | %(name)s |  %(levelname)s: %(message)s')
    logger.setLevel(logging.DEBUG)

    logFilePath = "my.log"
    file_handler = logging.FileHandler(filename=logFilePath)
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.DEBUG)
    logger.addHandler(file_handler)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainapp = MainApp()
    setup_logging()
    logging.getLogger().addHandler(mainapp.logger)

    formatter = logging.Formatter(
        '%(asctime)s | %(name)s |  %(levelname)s: %(message)s')

    logFilePath = "my.log"

    file_handler = logging.FileHandler(filename=logFilePath)
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.ERROR)
    logging.getLogger().addHandler(file_handler)
    mainapp.start()

    sys.exit(app.exec_())

dashboard.py

class QTextEditLogger(logging.Handler):

    class Signal(QObject):
        signal_log_append = pyqtSignal(str)
        def __init__(self, parent=None):
            super().__init__(parent=parent)
    

    def __init__(self, parent:QTextEdit):
        super().__init__()
        self.widget = parent
        self.widget.setReadOnly(True)
        self.signal = self.Signal(None)

    def emit(self, record):
        msg = self.format(record)
        self.signal.signal_log_append.emit(msg)

class MainApp(QMainWindow):
    self.logger = QTextEditLogger(self.ui.text_log)
    self.logger.signal.signal_log_append.connect(self.log)

解决方案

要实现QTextEdit仅接收DEBUG级日志,核心是给自定义的日志处理器添加级别过滤器——因为默认的setLevel只能设置最低接收级别(会包含所有更高等级的日志),无法精确筛选单一级别。

1. 给QTextEditLogger添加单一级别过滤器

修改dashboard.py中的QTextEditLogger类,添加过滤器函数只放行DEBUG级日志:

class QTextEditLogger(logging.Handler):

    class Signal(QObject):
        signal_log_append = pyqtSignal(str)
        def __init__(self, parent=None):
            super().__init__(parent=parent)
    

    def __init__(self, parent:QTextEdit):
        super().__init__()
        self.widget = parent
        self.widget.setReadOnly(True)
        self.signal = self.Signal(None)
        # 添加自定义过滤器,仅保留DEBUG级日志
        self.addFilter(self.debug_only_filter)
    
    def debug_only_filter(self, record):
        # 只返回级别为DEBUG的日志记录
        return record.levelno == logging.DEBUG

    def emit(self, record):
        msg = self.format(record)
        self.signal.signal_log_append.emit(msg)

class MainApp(QMainWindow):
    self.logger = QTextEditLogger(self.ui.text_log)
    self.logger.signal.signal_log_append.connect(self.log)

2. 简化日志配置逻辑,避免重复

当前代码存在重复配置日志处理器的问题,建议统一在主函数中配置,避免日志重复输出:

修改main.py的主函数部分:

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainapp = MainApp()
    
    # 获取根日志器,统一配置
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.DEBUG)  # 根日志器设为DEBUG,确保所有级别日志能传递到处理器
    
    # 配置QTextEdit处理器
    text_edit_formatter = logging.Formatter('%(asctime)s | %(name)s |  %(levelname)s: %(message)s')
    mainapp.logger.setFormatter(text_edit_formatter)
    root_logger.addHandler(mainapp.logger)
    
    # 配置文件处理器(仅ERROR级)
    logFilePath = "my.log"
    file_handler = logging.FileHandler(filename=logFilePath)
    file_formatter = logging.Formatter('%(asctime)s | %(name)s |  %(levelname)s: %(message)s')
    file_handler.setFormatter(file_formatter)
    file_handler.setLevel(logging.ERROR)
    root_logger.addHandler(file_handler)
    
    mainapp.start()
    sys.exit(app.exec_())

同时可以删除原有的setup_logging函数,避免不必要的日志实例创建。

关键说明

  • logging的setLevel()方法是设置最低接收阈值,比如设为DEBUG会接收所有>=DEBUG的日志(包括INFO、ERROR等),所以必须用自定义过滤器来精确筛选单一级别。
  • 过滤器函数debug_only_filter会检查每条日志的级别号,只有等于logging.DEBUG的才会被发送到QTextEdit。
  • 根日志器的级别要设置为DEBUG,确保所有级别的日志都能传递到各个处理器,再由处理器自己的规则过滤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:25:20