pyqt5+logging模块,在界面上实时显示日志
简介
在写小工具时,使用pyqt5生成界面,在代码中使用logging模块来打印信息,现在希望能将logging打印的信息实时展示在界面上,避免主程序运行时整个界面卡住的状态。
代码实现
通过两py文件来实现:
- logging_handler.py 在代码中,我们使用logging模块来记录日志,不仅可以方便的自定义日志格式,还能随时在希望的地方插入日志。
- main.py 使用pyqt5实现页面,配置控件,并通过threading模块实现子线程实时打印日志。
logging.Handler重写
我们需要写一个logging.Handler的子类,并重写其emit的方法,emit方法的官方介绍如下:
emit(record)
Do whatever it takes to actually log the specified logging record. This version is intended to be implemented by subclasses and so raises a NotImplementedError.
可以对指定的日志记录做任务事。(写到数据库、存到本地等都可以)
logging_handler代码如下:
import logging
from PyQt5.QtWidgets import QTextBrowser
# 设置全局的日志记录格式和日志等级
logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s %(message)s", level=logging.INFO)
class QTextBrowerHandler(logging.Handler):
"""
接收一个接数text_browser,他是一个pyqt5的QTextBrowser控件,特征是不可编辑的文本框,适合用来记录日志
"""
def __init__(self, text_browser: QTextBrowser):
super().__init__()
self.text_browser = text_browser
# 给此handler定义日志的格式
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
self.setFormatter(formatter)
def emit(self, record):
"""日志处理函数,格式化日志数据后,写入到QTextBrower控件中"""
msg = self.format(record)
self.text_browser.append(msg)
# 创建一个logger实例,其他模块引用该实例来记录日志
logger = logging.getLogger()
界面创建与日志实时打印
main.py代码如下
from PyQt5.QtWidgets import QWidget, QTextBrowser, QFrame, QGridLayout, QLabel, QPushButton, QApplication
import time, sys
from logging_handler import logger, QTextBrowerHandler
import threading
class MyTest(QWidget):
def __init__(self):
super(MyTest, self).__init__()
self.initUI()
self.setWindowTitle('devops_it')
self.setGeometry(300, 100, 800, 800)
self.show()
def initUI(self):
self.page_frame = QFrame(self)
self.grid = grid = QGridLayout(self.page_frame)
self.setLayout(grid)
# 配置各个控件,布局页面
log_label = QLabel('日志记录')
log_edit = QTextBrowser()
log_bt = QPushButton('程序启动')
log_bt.clicked.connect(self.log_print)
# 将自定义的handler绑定QTextBrowser控件实例后,再绑定到logger实例上
handler = QTextBrowerHandler(log_edit)
logger.addHandler(handler)
grid.addWidget(log_label, 0, 0)
grid.addWidget(log_bt, 0, 1)
grid.addWidget(log_edit, 1, 0)
def log_print(self):
"""按钮触发的函数"""
def func():
for i in range(10):
logger.info('我正在打印日志%s'%i)
logger.info('我等待一秒')
time.sleep(1)
# 创建子线程,主线程不阻塞同步执行指定函数
added_thread = threading.Thread(target=func)
added_thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyTest()
sys.exit(app.exec_())
执行main.py
实现效果如下,持续实时打印