phabricator arc diff --raw-command 报错:500 - 服务器错误

博客讲述了phabricator生成diff时出现报错,错误信息为‘[HTTP/500] Internal Server Error’。经追查,原因是有文件编码格式为ISO - 8859。可在Vim界面将文件编码转换成utf - 8,或使用文本编辑器转换,再次执行问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

phabricator生成diff报错:

arcanist/bin/arc diff --raw-command ‘git diff origin/master origin/xxxxxx -U20000’
报错:
Exception
[HTTP/500] Internal Server Error
500 - 服务器错误
追查原因是有个文件的编码格式是 ISO-8859
file xx/xx.conf
xx/xx.conf: ISO-8859 text, with CRLF line terminators

可以在Vim界面上直接转换文件编码,如转换成utf-8:
:set fileencoding=utf-8

或者使用文本编辑器也可以

再次执行问题解决了

# -*- coding:utf-8 -*- import os import sys import io import socket import time import re def read_config(): config = {} try: with open('config.txt', 'r') as config_file: for line in config_file: if '=' in line: key, value = line.strip().split('=', 1) config[key] = value print("Read config success.", flush=True) except FileNotFoundError: print("Unable to open config file!", flush=True) return None return config def is_command_available(command): """检查命令是否可用""" if os.name == 'nt': # Windows 系统 result = os.system(f'where {command} >nul 2>&1') else: # Linux 系统 result = os.system(f'which {command} >/dev/null 2>&1') return result == 0 def get_hardware_info(send_count): # 执行 cnmon info -e 命令并捕获输出 with os.popen('cnmon info -e') as f: result_temp = f.read() temperature_lines = extract_info(result_temp, "Temperature", "QDD Status") # 执行 cnmon info -p 命令并捕获输出 with os.popen('cnmon info -p') as f: result_power = f.read() power_lines = extract_info(result_power, "Power", "QDD Status") # 执行 cnmon info -m 命令并捕获输出 with os.popen('cnmon info -m') as f: result_memory = f.read() memory_lines = extract_info(result_memory, "v4.9.5", "Virtual Memory Usage") # 执行 cnmon info -b 命令并捕获输出 with os.popen('cnmon info -b') as f: result_bandwidth = f.read() bandwidth_lines = extract_info(result_bandwidth, "QDD 7 : Invalid", " Chassis") # 执行 cnmon info -u 命令并捕获输出 with os.popen('cnmon info -u') as f: result_usage = f.read() usage_lines = extract_info(result_usage, "Utilization", "QDD Status") usage_str = '\n'.join(usage_lines) mlu_average = 0 mlu_0 = 0 mlu_1 = 0 mlu_2 = 0 mlu_3 = 0 cpu_chip = 0 cpu_core_0 = 0 cpu_core_1 = 0 cpu_core_2 = 0 cpu_core_3 = 0 # 提取 MLU 平均利用率 mlu_avg_match = re.search(r'MLU Average\s+:\s+(\d+) %', usage_str) if mlu_avg_match: mlu_average = float(mlu_avg_match.group(1)) # 提取 MLU 0 - 3 利用率 mlu_0_3_match = re.search(r'MLU 0-3\s+:\s+(\d+) %\s+(\d+) %\s+(\d+) %\s+(\d+) %', usage_str) if mlu_0_3_match: mlu_0 = float(mlu_0_3_match.group(1)) mlu_1 = float(mlu_0_3_match.group(2)) mlu_2 = float(mlu_0_3_match.group(3)) mlu_3 = float(mlu_0_3_match.group(4)) # 提取 CPU 芯片利用率 cpu_chip_match = re.search(r'Device CPU Chip\s+:\s+(\d+) %', usage_str) if cpu_chip_match: cpu_chip = float(cpu_chip_match.group(1)) # 提取 CPU 核心 0 - 3 利用率 cpu_core_0_3_match = re.search(r'Device CPU Core 0-3\s+:\s+(\d+) %\s+(\d+) %\s+(\d+) %\s+(\d+) %', usage_str) if cpu_core_0_3_match: cpu_core_0 = float(cpu_core_0_3_match.group(1)) cpu_core_1 = float(cpu_core_0_3_match.group(2)) cpu_core_2 = float(cpu_core_0_3_match.group(3)) cpu_core_3 = float(cpu_core_0_3_match.group(4)) # 添加分隔符和发送次数 info_str = ( "温度信息:\n{}\n\n功率信息:\n{}\n\n内存信息:\n{}\n\n带宽信息:\n{}\n\nMLU信息:\nMLU Average: {}%\nMLU 0-3 利用率:\nMLU 0: {}%\nMLU 1: {}%\nMLU 2: {}%\nMLU 3: {}%\n\nCPU信息:\n" "Device CPU Chip: {}%\nCPU核心 0-3 利用率:\nDevice CPU Core 0: {}%\nDevice CPU Core 1: {}%\nDevice CPU Core 2: {}%\nDevice CPU Core 3: {}%\n发送次数:\nsend_count : {}次\n---------------END---------------" ).format( '\n'.join(temperature_lines), '\n'.join(power_lines), '\n'.join(memory_lines), '\n'.join(bandwidth_lines), mlu_average, mlu_0, mlu_1, mlu_2, mlu_3, cpu_chip, cpu_core_0, cpu_core_1, cpu_core_2, cpu_core_3, send_count ) return info_str def extract_info(result, start_keyword, end_keyword): """提取指定关键字之间的信息""" lines = result.splitlines() extracted = [] started = False for line in lines: if start_keyword in line: started = True elif started and line.strip(): if end_keyword in line: break extracted.append(line.strip()) return extracted def main(): # 设置无缓冲输出 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True) config = read_config() if config is None: return server_ip = config.get('SERVER_IP') server_port = int(config.get('SERVER_PORT')) client_ip = config.get('CLIENT_IP') client_port = int(config.get('CLIENT_PORT')) print(f"ServerIP: {server_ip}", flush=True) print(f"ServerPort: {server_port}", flush=True) print(f"ClientIP: {client_ip}", flush=True) print(f"ClientPort: {client_port}", flush=True) # 创建 UDP 套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 端口号快速重用 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) print("Set socket ok.", flush=True) # 绑定服务器 IP 和端口 try: sock.bind((server_ip, server_port)) print("Bind success.", flush=True) except OSError as e: print(f"Bind error: {e}", flush=True) return send_count = 1 try: while True: if not is_command_available('cnmon'): print("当前cnmon命令不可用,使用nmon功能", flush=True) info = ( "温度信息:\n" "Board : 34 C\n" "Cluster 0 : 36 C\n" "\n" "功率信息:\n" "Usage : 3.44 W\n" "Cap : 15 W\n" " \n" "内存信息:\n" "Physical Memory Usage :\n" "Total : 8192 MiB\n" "Used : 1669 MiB\n" "Free : 6523 MiB\n" "Channel Memory Usage :\n" " 0 : 1669 MiB\n" "DDR Data Widths : 64 bit\n" "DDR BandWidth : 29 GB/s\n" "\n" "带宽信息:\n" "Bandwidth : N/A\n" "\n" "CPU信息:\n" "Device CPU Chip: 6.0%\n" "CPU核心 0-3 利用率:\n" "Device CPU Core 0: 3.0%\n" "Device CPU Core 1: 20.0%\n" "Device CPU Core 2: 9.0%\n" "Device CPU Core 3: 3.0%\n" "\n" "---------------END---------------\n" ) else: print("获取硬件信息...", flush=True) info = get_hardware_info(send_count) try: sock.sendto(info.encode(), (client_ip, client_port)) print("Send data success:", flush=True) print(info, flush=True) # 确保输出立即显示 except OSError as e: print(f"Send error: {e}", flush=True) send_count += 1 time.sleep(0.5) except KeyboardInterrupt: print("Program interrupted by user.", flush=True) finally: sock.close() print("Socket closed.", flush=True) if __name__ == "__main__": main()这段MLU220服务端程序执行发出的文本数据能被下面这段客户端代码接收显示吗?import tkinter as tk import ttkbootstrap as tb import threading import socket import subprocess import time from ttkbootstrap.constants import * from PIL import Image, ImageTk, ImageDraw class MLUDataReceiver: def __init__(self, callback): self.callback = callback self.devices = { "设备1": { "ip": "192.168.0.0", "status": "离线", "temperature": 0, "power": 0, "memory": 0, "bandwidth": 0, "mlu_avg_usage": 0, "cpu_avg_usage": 0 } } self.current_device = "设备1" self.running = True self.start_udp_receive() def parse_info(self, info_str): info = {} sections = info_str.split("---------------END---------------")[0].split("\n\n") for section in sections: lines = [line.strip() for line in section.splitlines() if line.strip()] if not lines: continue key = lines[0].split(":")[0].strip() if key == "温度信息": info.update(self.parse_temperature(lines[1:])) elif key == "功率信息": info.update(self.parse_power(lines[1:])) elif key == "内存信息": info.update(self.parse_memory(lines)) elif key == "带宽信息": info.update(self.parse_bandwidth(lines[1:])) elif key == "MLU信息": info.update(self.parse_mlu_avg_usage(lines)) elif key == "CPU信息": info.update(self.parse_cpu_avg_usage(lines)) return info def parse_temperature(self, lines): temp = 0 for line in lines: if "C" in line: try: temp = max(temp, float(line.split(":")[1].strip().replace(" C", ""))) except (IndexError, ValueError): continue return {"temperature": temp} def parse_power(self, lines): power = 0 for line in lines: if "W" in line: try: power = float(line.split(":")[1].strip().replace(" W", "")) except (IndexError, ValueError): continue return {"power": power} def parse_memory(self, lines): total = 0 used = 0 physical_memory_section = False for line in lines: if "Physical Memory Usage" in line: physical_memory_section = True elif physical_memory_section: if "Total" in line: total = self.parse_memory_value(line) elif "Used" in line: used = self.parse_memory_value(line) return {"memory": round(used / total * 100, 1) if total != 0 else 0} def parse_memory_value(self, line): try: value = line.split(":")[1].strip() num = float(value.split()[0]) unit = value.split()[1] if unit == "MiB": return num * 1024 * 1024 return num except (IndexError, ValueError): return 0 def parse_bandwidth(self, lines): bandwidth = 0 for line in lines: if "GB/s" in line: try: bandwidth = float(line.split(":")[1].strip().replace(" GB/s", "")) except (IndexError, ValueError): continue return {"bandwidth": bandwidth} def parse_mlu_avg_usage(self, lines): for line in lines: if "MLU Average" in line: try: parts = line.split(':') if len(parts) > 1: mlu_avg_usage = float(parts[1].strip().replace("%", "")) return {"mlu_avg_usage": mlu_avg_usage} except (IndexError, ValueError): continue return {"mlu_avg_usage": 0} def parse_cpu_avg_usage(self, lines): for line in lines: if "Device CPU Chip" in line: try: parts = line.split(':') if len(parts) > 1: cpu_avg_usage = float(parts[1].strip().replace("%", "")) return {"cpu_avg_usage": cpu_avg_usage} except (IndexError, ValueError): continue return {"cpu_avg_usage": 0} def start_udp_receive(self): def read_config(): config = {} try: with open('config.txt', 'r') as config_file: for line in config_file: if '=' in line: key, value = line.strip().split('=', 1) config[key] = value print("Read config success.") except FileNotFoundError: print("Unable to open config file!") return None return config config = read_config() if config is None: return server_ip = config.get('SERVER_IP') server_port = int(config.get('SERVER_PORT')) client_ip = config.get('CLIENT_IP') client_port = int(config.get('CLIENT_PORT')) print("ServerIP: {}".format(server_ip)) print("ServerPort: {}".format(server_port)) print("ClientIP: {}".format(client_ip)) print("ClientPort: {}".format(client_port)) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) print("Set socket ok.") try: sock.bind((client_ip, client_port)) print("Bind success.") except OSError: print("Bind error!") return def receive_data(): print("Start receive data.") try: while self.running: data, addr = sock.recvfrom(4096) try: info_str = data.decode('utf-8') device = self.devices[self.current_device] # ping检测逻辑 ip = device["ip"] try: result = subprocess.run(['ping', '-c', '1', '-W', '1', ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if result.returncode == 0: device["status"] = "在线" else: device["status"] = "离线" except Exception as e: print(f"Ping 检测出错: {e}") device["status"] = "离线" # 解析数据并更新设备信息 info = self.parse_info(info_str) device.update(info) # 通过回调传递数据 self.callback({ 'cpu_temp': device['temperature'], 'power': device['power'], 'mem_usage': device['memory'], 'bandwidth': device['bandwidth'] * 8000, # 转换为Mbps 'mlu_usage': device['mlu_avg_usage'], 'cpu_usage': device['cpu_avg_usage'], 'status': device['status'] }) except UnicodeDecodeError: print("解码数据时出错,请检查数据编码。") except OSError: print("Receive data error!") except Exception as e: print(f"Unexpected error: {e}") finally: sock.close() receive_thread = threading.Thread(target=receive_data) receive_thread.daemon = True receive_thread.start() def stop(self): self.running = False class EnhancedCircularProgressBar: def __init__(self, parent, size=200, thickness=20, bg_color="#1a1a1a", text_color="#ffffff", font_size=16, title="", unit="", max_value=100, glow_effect=True): self.parent = parent self.size = size self.thickness = thickness self.bg_color = bg_color self.text_color = text_color self.font_size = font_size self.title = title self.unit = unit self.max_value = max_value self.glow_effect = glow_effect self.current_value = 0 self.target_value = 0 self.animation_speed = 1.0 # 动画速度因子 # 创建画布 self.canvas = tk.Canvas( parent, width=size, height=size, bg="black", highlightthickness=0, bd=0 ) # 计算圆心和半径 self.center_x = size / 2 self.center_y = size / 2 self.radius = (size - thickness) / 2 - 5 # 绘制背景圆环 self.draw_background() # 绘制文本 self.text_id = self.canvas.create_text( self.center_x, self.center_y, text="0%", fill=text_color, font=("Arial", font_size, "bold") ) # 绘制标题 self.title_id = self.canvas.create_text( self.center_x, self.center_y + 40, text=title, fill=text_color, font=("Arial", int(font_size*0.8)) ) # 初始绘制 self.set_value(0) def draw_background(self): """绘制背景圆环""" # 计算圆环的外接矩形坐标 x0 = self.center_x - self.radius y0 = self.center_y - self.radius x1 = self.center_x + self.radius y1 = self.center_y + self.radius # 绘制背景圆环 self.bg_arc = self.canvas.create_arc( x0, y0, x1, y1, start=0, # 起始角度 extent=360, # 360度完整圆环 width=self.thickness, outline=self.bg_color, style=tk.ARC ) def interpolate_color(self, progress): """根据进度值插值计算颜色(绿---红过渡)""" # 定义颜色过渡点 color_points = [ (0.00, (0, 255, 0)), # 绿色 (0.25, (170, 255, 0)), # 黄绿色 (0.50, (255, 255, 0)), # 黄色 (0.75, (255, 170, 0)), # 橙色 (1.00, (255, 0, 0)) # 红色 ] # 找到当前进度所在的区间 for i in range(1, len(color_points)): if progress <= color_points[i][0]: # 计算区间内的比例 t = (progress - color_points[i-1][0]) / (color_points[i][0] - color_points[i-1][0]) # 线性插值计算RGB值(不使用numpy) r1, g1, b1 = color_points[i-1][1] r2, g2, b2 = color_points[i][1] r = int(r1 + t * (r2 - r1)) g = int(g1 + t * (g2 - g1)) b = int(b1 + t * (b2 - b1)) return f"#{r:02x}{g:02x}{b:02x}" # 默认返回红色 return "#ff0000" def set_value(self, value, animate=True): """设置当前值并更新进度条""" # 确保值在合理范围内 value = max(0, min(value, self.max_value)) if animate: self.target_value = value # 启动动画(如果尚未运行) if abs(self.current_value - self.target_value) > 0.1: self.animate_step() else: self.target_value = value self.current_value = value self.update_display() def update_display(self): """更新进度条显示""" # 计算进度比例 progress = self.current_value / self.max_value # 计算角度(从-90度开始,即12点钟方向) angle = progress * 360 # 清除旧的前景圆环 if hasattr(self, 'fg_arc'): self.canvas.delete(self.fg_arc) # 计算圆环的外接矩形坐标 x0 = self.center_x - self.radius y0 = self.center_y - self.radius x1 = self.center_x + self.radius y1 = self.center_y + self.radius # 获取插值颜色 color = self.interpolate_color(progress) # 绘制前景圆环(进度指示) self.fg_arc = self.canvas.create_arc( x0, y0, x1, y1, start=90, # 从12点钟方向开始 extent=angle, # 根据值计算角度 width=self.thickness, outline=color, style=tk.ARC ) # 提升前景圆环的显示层级 self.canvas.tag_raise(self.fg_arc) # 更新文本显示 display_text = f"{self.current_value:.1f}" if self.unit == "%": display_text = f"{progress*100:.1f}%" self.canvas.itemconfig(self.text_id, text=display_text) def animate_step(self): """执行一步动画(不使用numpy)""" if abs(self.current_value - self.target_value) < 0.1: self.current_value = self.target_value else: # 使用缓动函数实现平滑动画 diff = self.target_value - self.current_value self.current_value += diff * 0.2 * self.animation_speed self.update_display() # 如果未达到目标值,继续动画 if abs(self.current_value - self.target_value) > 0.1: self.parent.after(16, self.animate_step) # 约60fps class SystemMonitorApp: def __init__(self): # 创建主窗口 self.root = tb.Window(themename="darkly", title="系统资源监控", size=(1300, 800)) self.root.minsize(1000, 700) # 设置样式 style = tb.Style() style.configure("TFrame", background="#121212") style.configure("Title.TLabel", background="#121212", foreground="#e0e0e0", font=("Arial", 16, "bold")) style.configure("Section.TLabelframe", font=("Arial", 10, "bold")) # 创建主框架 - 使用网格布局 main_frame = tb.Frame(self.root, padding=10) main_frame.pack(fill=tk.BOTH, expand=True) # ========== 顶部控制栏 ========== control_bar = tb.Frame(main_frame, padding=(10, 5)) control_bar.grid(row=0, column=0, columnspan=3, sticky="ew", pady=(0, 10)) # 设备选择下拉框 tb.Label(control_bar, text="监控设备:", bootstyle=PRIMARY).pack(side=tk.LEFT, padx=(0, 5)) self.device_var = tk.StringVar() device_options = ["设备1"] # 只监控一个设备 device_combo = tb.Combobox( control_bar, textvariable=self.device_var, values=device_options, width=15, state="readonly", bootstyle=PRIMARY ) device_combo.pack(side=tk.LEFT, padx=5) device_combo.current(0) # 设置默认选项 # 采样频率滑块 tb.Label(control_bar, text="采样频率:", bootstyle=PRIMARY).pack(side=tk.LEFT, padx=(20, 5)) self.sampling_rate = tk.IntVar(value=1) tb.Scale( control_bar, from_=0.5, to=5, length=120, orient=tk.HORIZONTAL, variable=self.sampling_rate, bootstyle=PRIMARY ).pack(side=tk.LEFT, padx=5) # 动画速度滑块 tb.Label(control_bar, text="动画速度:", bootstyle=PRIMARY).pack(side=tk.LEFT, padx=(20, 5)) self.animation_speed = tk.DoubleVar(value=1.0) tb.Scale( control_bar, from_=0.5, to=3.0, length=120, orient=tk.HORIZONTAL, variable=self.animation_speed, bootstyle=PRIMARY ).pack(side=tk.LEFT, padx=5) # 控制按钮 tb.Button( control_bar, text="启动", bootstyle=SUCCESS, width=8, command=self.start_monitoring ).pack(side=tk.LEFT, padx=5) tb.Button( control_bar, text="暂停", bootstyle=DANGER, width=8, command=self.stop_monitoring ).pack(side=tk.LEFT, padx=5) tb.Button( control_bar, text="重置", bootstyle=WARNING, width=8, command=self.reset_all ).pack(side=tk.LEFT, padx=5) # 状态指示器 self.status_indicator = tb.Label( control_bar, text="● 等待连接", bootstyle=(WARNING, INVERSE), font=("Arial", 10), padding=(10, 0) ) self.status_indicator.pack(side=tk.RIGHT, padx=(10, 0)) # ========== 左侧设置面板 ========== settings_frame = tb.Labelframe( main_frame, text="监控设置", bootstyle="info", padding=10, style="Section.TLabelframe" ) settings_frame.grid(row=1, column=0, sticky="nsew", padx=(0, 10), pady=(0, 10)) # 温度报警设置 temp_frame = tb.Frame(settings_frame) temp_frame.pack(fill=tk.X, pady=5) tb.Label(temp_frame, text="温度报警阈值(°C):").pack(side=tk.LEFT) self.temp_threshold = tk.IntVar(value=80) tb.Entry( temp_frame, textvariable=self.temp_threshold, width=8, bootstyle=PRIMARY ).pack(side=tk.RIGHT, padx=(5, 0)) # 内存报警设置 mem_frame = tb.Frame(settings_frame) mem_frame.pack(fill=tk.X, pady=5) tb.Label(mem_frame, text="内存报警阈值(%):").pack(side=tk.LEFT) self.mem_threshold = tk.IntVar(value=90) tb.Entry( mem_frame, textvariable=self.mem_threshold, width=8, bootstyle=PRIMARY ).pack(side=tk.RIGHT, padx=(5, 0)) # 网络报警设置 net_frame = tb.Frame(settings_frame) net_frame.pack(fill=tk.X, pady=5) tb.Label(net_frame, text="网络报警阈值(Mbps):").pack(side=tk.LEFT) self.net_threshold = tk.IntVar(value=800) tb.Entry( net_frame, textvariable=self.net_threshold, width=8, bootstyle=PRIMARY ).pack(side=tk.RIGHT, padx=(5, 0)) # 分隔线 tb.Separator(settings_frame, bootstyle=SECONDARY).pack(fill=tk.X, pady=10) # 主题选择 tb.Label(settings_frame, text="界面主题:", bootstyle=PRIMARY).pack(anchor=tk.W, pady=(0, 5)) self.theme_var = tk.StringVar(value="darkly") themes = ["darkly", "solar", "superhero", "cyborg", "vapor"] tb.Combobox( settings_frame, textvariable=self.theme_var, values=themes, state="readonly", bootstyle=PRIMARY ).pack(fill=tk.X, pady=(0, 10)) # 历史数据按钮 tb.Button( settings_frame, text="查看历史数据", bootstyle=(OUTLINE, INFO), command=self.show_history ).pack(fill=tk.X, pady=5) # ========== 中间监控面板 ========== monitor_frame = tb.Frame(main_frame) monitor_frame.grid(row=1, column=1, sticky="nsew", pady=(0, 10)) # 标题 tb.Label( monitor_frame, text="系统资源实时监控", style="Title.TLabel" ).pack(pady=(0, 15)) # 创建进度条容器框架 progress_container = tb.Frame(monitor_frame) progress_container.pack(fill=tk.BOTH, expand=True, pady=5) # 创建监控指标配置 monitor_config = [ {"title": "CPU温度", "unit": "°C", "max_value": 100, "thickness": 18}, {"title": "功耗", "unit": "W", "max_value": 200, "thickness": 18}, {"title": "内存使用", "unit": "%", "max_value": 100, "thickness": 18}, {"title": "网络带宽", "unit": "Mbps", "max_value": 1000, "thickness": 18}, {"title": "MLU利用率", "unit": "%", "max_value": 100, "thickness": 18}, {"title": "CPU利用率", "unit": "%", "max_value": 100, "thickness": 18} ] # 使用网格布局排列进度条 self.progress_bars = [] for i, config in enumerate(monitor_config): frame = tb.Frame(progress_container) frame.grid(row=i//3, column=i%3, padx=15, pady=15, sticky="nsew") # 创建增强型进度条 progress_bar = EnhancedCircularProgressBar( frame, size=220, thickness=config["thickness"], title=config["title"], unit=config["unit"], max_value=config["max_value"], glow_effect=True ) self.progress_bars.append(progress_bar) progress_bar.canvas.pack(fill=tk.BOTH, expand=True) # 设置网格列权重 for i in range(3): progress_container.columnconfigure(i, weight=1) for i in range(2): progress_container.rowconfigure(i, weight=1) # ========== 右侧信息面板 ========== info_frame = tb.Labelframe( main_frame, text="系统信息", bootstyle="info", padding=10, style="Section.TLabelframe" ) info_frame.grid(row=1, column=2, sticky="nsew", padx=(10, 0), pady=(0, 10)) # 系统信息标签 info_labels = [ ("设备型号:", "MLU220"), ("操作系统:", "Ubuntu 20.04 LTS"), ("处理器:", "4核 ARMv8"), ("内存总量:", "8 GB"), ("MLU数量:", "1"), ("网络接口:", "eth0 (10Gbps)") ] for label, value in info_labels: frame = tb.Frame(info_frame) frame.pack(fill=tk.X, pady=3) tb.Label(frame, text=label, width=10, anchor=tk.W).pack(side=tk.LEFT) tb.Label(frame, text=value, bootstyle=INFO).pack(side=tk.LEFT) # 分隔线 tb.Separator(info_frame, bootstyle=SECONDARY).pack(fill=tk.X, pady=10) # 实时状态 tb.Label(info_frame, text="实时状态", bootstyle=PRIMARY).pack(anchor=tk.W, pady=(0, 5)) self.realtime_labels = {} status_items = [ ("CPU温度", "cpu_temp", "°C"), ("功耗", "power", "W"), ("内存使用", "memory", "%"), ("网络带宽", "bandwidth", "Mbps"), ("MLU利用率", "mlu_usage", "%"), ("CPU利用率", "cpu_usage", "%") ] for name, key, unit in status_items: frame = tb.Frame(info_frame) frame.pack(fill=tk.X, pady=2) tb.Label(frame, text=name, width=12, anchor=tk.W).pack(side=tk.LEFT) value_label = tb.Label(frame, text="0.0", width=8, anchor=tk.W) value_label.pack(side=tk.LEFT) tb.Label(frame, text=unit).pack(side=tk.LEFT) self.realtime_labels[key] = value_label # ========== 状态栏 ========== self.status = tb.Label( self.root, text="系统准备就绪 | 当前设备: 设备1", bootstyle=(SECONDARY, INVERSE), anchor=tk.CENTER ) self.status.pack(side=tk.BOTTOM, fill=tk.X) # 配置网格权重 main_frame.columnconfigure(0, weight=1) # 左侧设置面板 main_frame.columnconfigure(1, weight=3) # 中间监控面板主要区域 main_frame.columnconfigure(2, weight=1) # 右侧信息面板 main_frame.rowconfigure(1, weight=1) # 监控控制变量 self.monitoring_active = False self.monitoring_thread = None # 创建数据接收器 self.data_receiver = MLUDataReceiver(self.data_received) # 绑定主题切换事件 self.theme_var.trace_add("write", lambda *args: self.change_theme()) # 初始状态 self.status_indicator.config(text="● 等待数据", bootstyle=(WARNING, INVERSE)) self.root.mainloop() def data_received(self, data): """从MLUDataReceiver接收数据的回调函数""" if not self.monitoring_active: return # 更新状态指示器 if data['status'] == "在线": self.status_indicator.config(text="● 已连接", bootstyle=(SUCCESS, INVERSE)) else: self.status_indicator.config(text="● 设备离线", bootstyle=(DANGER, INVERSE)) # 使用after安全更新UI self.root.after(0, self.update_ui, data) def start_monitoring(self): """启动资源监控""" if self.monitoring_active: return self.status.config(text="启动系统资源监控...") self.monitoring_active = True self.status_indicator.config(text="● 接收数据中...", bootstyle=(INFO, INVERSE)) def stop_monitoring(self): """停止资源监控""" self.monitoring_active = False self.status.config(text="监控已暂停") self.status_indicator.config(text="● 监控暂停", bootstyle=(WARNING, INVERSE)) def reset_all(self): """重置所有监控指标""" for bar in self.progress_bars: bar.set_value(0) self.status.config(text="所有监控指标已重置") def change_theme(self): """更改应用主题""" theme = self.theme_var.get() # 正确切换主题方法 self.root.style.theme_use(theme) self.status.config(text=f"主题已切换为: {theme.capitalize()}") def show_history(self): """显示历史数据""" self.status.config(text="历史数据查看功能开发中...") def update_ui(self, data): """安全更新UI组件(在主线程执行)""" # 更新进度条的动画速度 speed = self.animation_speed.get() for bar in self.progress_bars: bar.animation_speed = speed # 更新进度条 self.progress_bars[0].set_value(data['cpu_temp']) self.progress_bars[1].set_value(data['power']) self.progress_bars[2].set_value(data['mem_usage']) self.progress_bars[3].set_value(data['bandwidth']) self.progress_bars[4].set_value(data['mlu_usage']) self.progress_bars[5].set_value(data['cpu_usage']) # 更新实时状态标签 self.realtime_labels["cpu_temp"].config(text=f"{data['cpu_temp']:.1f}") self.realtime_labels["power"].config(text=f"{data['power']:.1f}") self.realtime_labels["memory"].config(text=f"{data['mem_usage']:.1f}") self.realtime_labels["bandwidth"].config(text=f"{data['bandwidth']:.1f}") self.realtime_labels["mlu_usage"].config(text=f"{data['mlu_usage']:.1f}") self.realtime_labels["cpu_usage"].config(text=f"{data['cpu_usage']:.1f}") # 更新状态栏 status_text = ( f"当前设备: {self.device_var.get()} | " f"状态: {data['status']} | " f"CPU: {data['cpu_usage']:.1f}% | " f"温度: {data['cpu_temp']:.1f}°C | " f"内存: {data['mem_usage']:.1f}% | " f"MLU: {data['mlu_usage']:.1f}%" ) self.status.config(text=status_text) def on_closing(self): """窗口关闭时的清理操作""" if hasattr(self, 'data_receiver'): self.data_receiver.stop() self.root.destroy() if __name__ == "__main__": app = SystemMonitorApp()
最新发布
06-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值