优化日志查看器
This commit is contained in:
@@ -5,7 +5,7 @@ import queue
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
from collections import defaultdict
|
from collections import deque
|
||||||
|
|
||||||
# 设置应用的外观模式和默认颜色主题
|
# 设置应用的外观模式和默认颜色主题
|
||||||
ctk.set_appearance_mode("dark")
|
ctk.set_appearance_mode("dark")
|
||||||
@@ -24,7 +24,7 @@ class LogViewerApp(ctk.CTk):
|
|||||||
# 初始化进程、日志队列、日志数据等变量
|
# 初始化进程、日志队列、日志数据等变量
|
||||||
self.process = None
|
self.process = None
|
||||||
self.log_queue = queue.Queue()
|
self.log_queue = queue.Queue()
|
||||||
self.log_data = []
|
self.log_data = deque(maxlen=10000) # 使用固定长度队列
|
||||||
self.available_levels = set()
|
self.available_levels = set()
|
||||||
self.available_modules = set()
|
self.available_modules = set()
|
||||||
self.sorted_modules = []
|
self.sorted_modules = []
|
||||||
@@ -142,28 +142,24 @@ class LogViewerApp(ctk.CTk):
|
|||||||
"""在指定父组件中添加复选框"""
|
"""在指定父组件中添加复选框"""
|
||||||
|
|
||||||
def update_filter():
|
def update_filter():
|
||||||
|
current = cb.get()
|
||||||
if type_ == "level":
|
if type_ == "level":
|
||||||
if cb.get():
|
(self.selected_levels.add if current else self.selected_levels.discard)(text)
|
||||||
self.selected_levels.add(text)
|
else:
|
||||||
else:
|
(self.selected_modules.add if current else self.selected_modules.discard)(text)
|
||||||
self.selected_levels.discard(text)
|
|
||||||
elif type_ == "module":
|
|
||||||
if cb.get():
|
|
||||||
self.selected_modules.add(text)
|
|
||||||
else:
|
|
||||||
self.selected_modules.discard(text)
|
|
||||||
self.refresh_logs()
|
self.refresh_logs()
|
||||||
|
|
||||||
cb = ctk.CTkCheckBox(parent, text=text, command=update_filter)
|
cb = ctk.CTkCheckBox(parent, text=text, command=update_filter)
|
||||||
cb.select() # 默认选中
|
cb.select() # 初始选中
|
||||||
|
|
||||||
# 记录初始选中状态
|
# 手动同步初始状态到集合(关键修复)
|
||||||
if type_ == "level":
|
if type_ == "level":
|
||||||
self.selected_levels.add(text)
|
self.selected_levels.add(text)
|
||||||
elif type_ == "module":
|
else:
|
||||||
self.selected_modules.add(text)
|
self.selected_modules.add(text)
|
||||||
self.module_checkboxes[text] = cb # 存储模块复选框引用
|
|
||||||
|
|
||||||
|
if type_ == "module":
|
||||||
|
self.module_checkboxes[text] = cb
|
||||||
cb.pack(anchor="w", padx=5, pady=2)
|
cb.pack(anchor="w", padx=5, pady=2)
|
||||||
return cb
|
return cb
|
||||||
|
|
||||||
@@ -199,29 +195,34 @@ class LogViewerApp(ctk.CTk):
|
|||||||
"""停止日志进程并清理相关资源"""
|
"""停止日志进程并清理相关资源"""
|
||||||
if self.process:
|
if self.process:
|
||||||
try:
|
try:
|
||||||
# 终止整个进程组(Windows需要特殊处理)
|
|
||||||
if hasattr(self.process, "pid"):
|
if hasattr(self.process, "pid"):
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(self.process.pid)], check=True)
|
subprocess.run(
|
||||||
|
["taskkill", "/F", "/T", "/PID", str(self.process.pid)], check=True, capture_output=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
|
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
|
||||||
except Exception as e:
|
except (subprocess.CalledProcessError, ProcessLookupError, OSError) as e:
|
||||||
print(f"Error terminating process: {e}")
|
print(f"终止进程失败: {e}")
|
||||||
finally:
|
finally:
|
||||||
self.process = None
|
self.process = None
|
||||||
# 清理队列和重置界面状态
|
|
||||||
self.log_queue.queue.clear()
|
self.log_queue.queue.clear()
|
||||||
self.start_btn.configure(state="normal")
|
self.start_btn.configure(state="normal")
|
||||||
self.stop_btn.configure(state="disabled")
|
self.stop_btn.configure(state="disabled")
|
||||||
# 强制刷新日志显示
|
|
||||||
self.refresh_logs()
|
self.refresh_logs()
|
||||||
|
|
||||||
def read_output(self):
|
def read_output(self):
|
||||||
"""读取日志进程的输出并放入队列"""
|
"""读取日志进程的输出并放入队列"""
|
||||||
while self.process and self.process.poll() is None:
|
try:
|
||||||
line = self.process.stdout.readline()
|
while self.process and self.process.poll() is None:
|
||||||
if line:
|
line = self.process.stdout.readline()
|
||||||
self.log_queue.put(line)
|
if line:
|
||||||
|
self.log_queue.put(line)
|
||||||
|
else:
|
||||||
|
break # 避免空循环
|
||||||
|
self.process.stdout.close() # 确保关闭文件描述符
|
||||||
|
except ValueError: # 处理可能的I/O操作异常
|
||||||
|
pass
|
||||||
|
|
||||||
def process_log_queue(self):
|
def process_log_queue(self):
|
||||||
"""处理日志队列中的日志条目"""
|
"""处理日志队列中的日志条目"""
|
||||||
@@ -258,8 +259,6 @@ class LogViewerApp(ctk.CTk):
|
|||||||
self.update_filters(level, module)
|
self.update_filters(level, module)
|
||||||
log_entry = {"raw": raw_line, "time": time, "level": level, "module": module, "message": message}
|
log_entry = {"raw": raw_line, "time": time, "level": level, "module": module, "message": message}
|
||||||
self.log_data.append(log_entry)
|
self.log_data.append(log_entry)
|
||||||
if len(self.log_data) > 10000:
|
|
||||||
self.log_data.pop(0)
|
|
||||||
|
|
||||||
if self.check_filter(log_entry):
|
if self.check_filter(log_entry):
|
||||||
self.display_log(log_entry)
|
self.display_log(log_entry)
|
||||||
|
|||||||
Reference in New Issue
Block a user