如何在While循环外部访问持续更新的CPU状态变量?
解决循环外部访问CPU监控数据的问题
原代码的核心问题
- 所有CPU监控相关变量(
maxfreq、curfreq、usage等)都是cpuinfo函数的局部变量,外部无法直接访问 - 初始化Tkinter标签时,
usage还未被线程赋值,会直接触发NameError - 在线程中直接调用
root.update()不符合Tkinter的线程安全规范,可能导致UI异常
修正后的代码
import psutil import threading import os from tkinter import Tk, Label # 全局变量存储CPU监控数据,供线程和主线程共享 cpu_freq_data = {} core_usages = [] total_cpu_usage = "" def cpuinfo(): global cpu_freq_data, core_usages, total_cpu_usage while True: # 更新CPU频率数据 cpufreq = psutil.cpu_freq() cpu_freq_data = { "max": f"Max Frequency: {cpufreq.max:.2f}Mhz", "min": f"Min Frequency: {cpufreq.min:.2f}Mhz", "current": f"Current Frequency: {cpufreq.current:.2f}Mhz" } # 批量更新所有核心的使用率(避免原代码中覆盖单个变量的问题) core_usages = [f"Core {i}: {percentage}%" for i, percentage in enumerate(psutil.cpu_percent(percpu=True, interval=1))] # 更新总CPU使用率 total_cpu_usage = f"Total CPU Usage: {psutil.cpu_percent()}%" def update_ui(): # 更新核心使用率标签 for idx, label in enumerate(core_labels): if idx < len(core_usages): label.config(text=core_usages[idx]) # 更新频率相关标签 max_freq_label.config(text=cpu_freq_data.get("max", "")) min_freq_label.config(text=cpu_freq_data.get("min", "")) cur_freq_label.config(text=cpu_freq_data.get("current", "")) # 更新总使用率标签 total_usage_label.config(text=total_cpu_usage) # 每隔1秒自动触发UI刷新 root.after(1000, update_ui) # 初始化Tkinter窗口 root = Tk() root.geometry("500x500") cores = os.cpu_count() or 1 # 创建CPU频率显示标签 max_freq_label = Label(root, text="") max_freq_label.pack() min_freq_label = Label(root, text="") min_freq_label.pack() cur_freq_label = Label(root, text="") cur_freq_label.pack() # 创建核心使用率标签并保存引用,方便后续更新 core_labels = [] for i in range(cores): label = Label(root, text=f"Core {i}: --%") label.pack() core_labels.append(label) # 创建总CPU使用率标签 total_usage_label = Label(root, text="") total_usage_label.pack() # 启动监控线程(设置daemon=True,关闭窗口时自动终止线程) monitor_thread = threading.Thread(target=cpuinfo, daemon=True) monitor_thread.start() # 启动UI定时刷新循环 update_ui() root.mainloop()
关键改进点
- 全局变量共享数据:通过
global声明,让监控线程可以更新全局变量,主线程的UI更新函数能直接读取最新数据 - 线程安全的UI操作:Tkinter要求所有UI操作必须在主线程执行,这里用
root.after()定时触发UI更新,避免跨线程操作UI的风险 - 批量存储核心数据:用列表
core_usages保存所有核心的使用率,解决原代码中单个变量被覆盖的问题 - 守护线程设置:给监控线程添加
daemon=True,确保关闭窗口时线程自动退出,不会残留后台进程
内容的提问来源于stack exchange,提问作者Canofeggs 5410
相关产品推荐
相关产品推荐

