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
相关产品推荐
相关产品推荐

