# logger_config_tkinter.py import logging import tkinter as tk from tkinter.scrolledtext import ScrolledText import queue class TkinterLogHandler(logging.Handler): """ 自定义的 logging 处理器,将日志消息发送到 Tkinter 文本控件。 使用队列确保线程安全。 """ def __init__(self, text_widget: ScrolledText): super().__init__() self.text_widget = text_widget self.queue = queue.Queue() self._schedule_check() def _schedule_check(self): """定期检查队列并更新 UI""" self._check_queue() # 每 100ms 检查一次队列 self.text_widget.after(100, self._schedule_check) def _check_queue(self): """处理队列中的日志消息""" try: while True: msg = self.queue.get_nowait() self._append_to_widget(msg) except queue.Empty: pass def _append_to_widget(self, msg): """将消息追加到文本控件""" try: self.text_widget.configure(state=tk.NORMAL) self.text_widget.insert(tk.END, msg + '\n') self.text_widget.see(tk.END) # 滚动到底部 self.text_widget.configure(state=tk.DISABLED) except Exception as e: # 如果控件已销毁,忽略错误 pass def emit(self, record): """ 处理日志记录,将其格式化并放入队列。 """ try: msg = self.format(record) self.queue.put(msg) except Exception: self.handleError(record) def setup_logging(text_widget: ScrolledText): """ 配置全局 logging,使其输出到控制台和指定的 Tkinter 文本控件。 """ root_logger = logging.getLogger() # 设置日志级别 root_logger.setLevel(logging.DEBUG) # 清除现有的处理器 for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) # 1. 控制台处理器 console_handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) # 2. Tkinter 文本控件处理器 text_handler = TkinterLogHandler(text_widget) text_handler.setFormatter(formatter) root_logger.addHandler(text_handler) return root_logger # 获取一个全局的 logger 实例 logger = logging.getLogger(__name__)