目录
前言
系统准备
软件下载与安装
安装相关库
程序准备
主体程序
更改后的程序:
编写.NET程序
前言
在现代生活中,电脑作为核心工具,其性能和稳定性的维护至关重要。为确保电脑高效运行,我们不仅需关注软件优化,如定期清理、安装防护软件、更新补丁和合理管理硬盘空间,还需重视硬件保养,特别是散热、定期硬件检查与适时升级。这些综合措施,有助于延长电脑寿命,提升使用体验。
本篇聚焦于利用Python这一强大工具,实现对GPU和CPU等关键硬件运行状况的实时监控。通过Python脚本,我们能够自动监测温度、负载等指标,及时发现潜在问题。这种技术应用不仅简化了维护流程,还提高了问题响应速度,是现代电脑维护策略中的重要一环。接下来,我们将深入探讨如何使用Python实现这些监控功能,为电脑的持续健康运行提供有力支持。
通过本篇的探讨,我们将掌握如何利用Python监控硬件,为个人电脑的高效管理和维护开辟新途径,让电脑在信息处理与科研探索中发挥更大效能。
诚邀各位大佬指正,我将不胜感激。
系统准备
软件下载与安装
我用的软件是PyCharm Community Edition 2023.1,下载安装请参考:
https://m.runoob.com/python3/https://m.runoob.com/python3/
安装相关库
我的电脑系统是Windows10,要实现监控CPU和NVIDIA GPU的温度等情况,采用的是psutil库读取CPU的特定数据,GPU则使用nvidia-ml-py3库。
nvidia-ml-py3库是一个用于管理和监控NVIDIA GPU的python接口,封装了NVML功能。通过它可以利用python代码查询GPU的状态,如温度、内存使用情况、计算利用率等等。
psutil库提供了丰富的接口来获取系统和进程的信息,包括CPU、内存、磁盘、网络等信息。
在pycharm中打开终端输入以下指令来安装其上两个库:
pip install psutil
pip install nvidia-ml-py3
window系统中pycharm打开终端的方法:
一、view-->Tool Windows-->Terminal
二、alt+F12
三、pycharm的左边竖着的工具栏中有终端图标点击即可。
图一
输入完安装指令后,如果出现以下提示,可以采用指令进行解决:
[notice] A new release of pip is available: 23.2.1 -> 24.0
[notice] To update, run: python.exe -m pip install --upgrade pip
指令:
python.exe -m pip install --upgrade pip
程序准备
主体程序
import time
import psutil
import pynvml
def get_cpu_info():
cpu_percent = psutil.cpu_percent(interval=1)
memory_info = psutil.virtual_memory()
memory_used = memory_info.percent
return cpu_percent, memory_used
def get_gpu_info(pynml=None):
try:
pynvml.nvmlInit()
device_count = pynvml.nvmlDeviceGetCount()
gpu_data = []
for i in range(decice_count):
handle = pynvml.nvmlDeviceGetHandleByIndex(i)
name = pynvml.nvmlDeviceGetName(handle)
util = pynml.nvmlDeviceGetUtilizationRates(handle)
gpu_util = util.gpu
temp = pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU)
mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
total_memory = mem_info.total / (1024 ** 2)
used_memory = mem_info.used / (1024 ** 2)
gpu_data.append({
'name': name,
'util': gpu_util,
'temp': temp,
'total_memory': total_memory,
'used_memory': used_memory
})
pynvml.nvmlShutdown()
return gpu_data
except pynvml.NVMLError as e:
print("Error while fetching GPU data: ", e)
return []
def main():
while True:
cpu_percent, memory_used = get_cpu_info()
print(f"CPU Usage: {cpu_percent}%")
print(f"Memory Usage: {memory_used}%")
gpu_data = get_gpu_info()
if gpu_data:
for gpu in gpu_data:
print(f"GPU {gpu['name']}:")
print(f" Utilization: {gpu['util']}%, Temperature: {gpu['temp']}°C")
print(f" Memory: {gpu['used_memory']} MB / {gpu['total_memory']} MB")
print("")
print("-" * 40)
time.sleep(5)
if __name__ == "__main__":
main()
解释:
添加了必要的库,其中的time让其能够更好的控制程序的更新频率,不至于太快给电脑太大的压力。
定义了三个函数,第一个是获取CPU的信息,第二个是获取GPU的信息,第三个是主函数。
在第一个函数中,我获取了CPU的使用率和内存的使用率,interval=1表示1秒的采样间隔,让我每隔一秒获取CPU的使用率。
在第二个函数中,因为获取GPU的相关信息比CPU要复杂一点,所以其函数也相应的复杂。先是初始化NVIDIA管理库,以便获取GPU信息,然后获取系统中的GPU的数量,其后初始化一个空列表以便储存GPU的相关信息。for是循环遍历每一个GPU,获取GPU的句柄,这是访问GPU的唯一标识,然后获取名称、使用率、温度、内存信息,我获取了GPU的总内存和已使用的内存,最终使用了gpu_data.append({})是以字典的形式来储存获取的GPU相关信息。
主函数,因为需要监控,所以利用while来循环。因为我们获取信息的动作已经完成,直接在其函数中书写打印显示我们想要的信息即可。
为了保证程序能够使用,进行了测试,结果对于GPU的采集发生了错误:
图二
这里的错误是指没有找到NVML的共享文件。
解决方法:
将nvml.dll文件添加到环境变量中。
先找到nvml.dll文件。
win+R打开命令提示符,输入cmd,最后输入
where nvidia-smi
找到了nvidia-smi.exe,nvml.dll文件与其在同一路径之下。
手动添加
进入设置中的关于-->点击高级系统设置-->在高级界面中点击环境变量-->找到系统变量区域下的path并选中,点击编辑-->在新的界面中点击新建-->添加路径,确认,重启电脑即可。
如果还未解决,怎采取以下方式:
下载CUDA Toolkit
要下载与自己的显卡驱动程序版本和系统架构相适应的CUDA Toolkit。
查看系统信息在任务栏中的搜索框中输入msinfo32,查看显卡的信息可在NVIDIA控制面板中点击帮助,点击系统信息即可查看。
我的系统可以支持12.6版本的,以下是下载地址:
https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=10&target_type=exe_local
下面的地址是查看自己的系统可以支持的版本:
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-major-component-versions__table-cuda-toolkit-driver-versions
安装完成之后,找到nvml.dll文件,更新环境变量。
由于我电脑比较差,没有多余空间安装CUDA,请各位大佬自行决定是否利用此方法观察是否有效,谢谢!
因此,我更换了库,pynvml库需要电脑中存在CUDA Toolkit才能运作,于是我更换了一个更加简单的库GUPtil。
更改后的程序:
import tkinter as tk # 导入tkinter库,用于创建GUI
import psutil # 导入psutil库,用于获取系统信息
import GPUtil # 导入GPUtil库,用于获取GPU信息
import subprocess # 导入subprocess库,用于执行系统命令
# 定义.NET程序路径
NET_PROGRAM_PATH = "D:\\CPU\\setup.exe"
def get_cpu_usage():
# 使用psutil获取CPU的使用率,参数2表示计算使用率的时间间隔,这里为2秒
return psutil.cpu_percent(interval=2)
def get_cpu_name():
# 尝试通过PowerShell命令获取CPU名称
try:
# 执行PowerShell命令并获取输出
cpu_info = subprocess.check_output(
"powershell -command \"Get-CimInstance Win32_Processor | Select-Object -ExpandProperty Name\"",
shell=True
).decode().strip() # 将输出解码为字符串并去除空格
return cpu_info if cpu_info else "未知CPU"
except Exception as e:
# 处理异常情况,打印错误信息并返回未知CPU
print(f"获取CPU名称时出错: {e}")
return "未知CPU"
def get_cpu_memory_usage():
# 使用psutil获取CPU的内存使用情况
memory = psutil.virtual_memory()
return {
'used_memory': f"{memory.used / (1024 ** 2):.1f} MB", # 已用内存,转换为MB
'total_memory': f"{memory.total / (1024 ** 2):.1f} MB" # 总内存,转换为MB
}
def get_gpu_info():
# 获取所有GPU的详细信息
gpus = GPUtil.getGPUs()
gpu_info = [] # 用于存储处理后的GPU信息
for gpu in gpus:
# 将GPU信息添加到字典中
gpu_info.append({
'id': gpu.id,
'name': gpu.name,
'load': f"{gpu.load * 100:.1f}%", # 载荷百分比
'temp': f"{gpu.temperature} °C", # 温度
'used_memory': f"{gpu.memoryUsed} MB", # 已用内存
'total_memory': f"{gpu.memoryTotal} MB" # 总内存
})
return gpu_info # 返回处理后的GPU信息列表
def update_info():
# 获取CPU使用率、名称和内存使用情况
cpu_usage = get_cpu_usage()
cpu_name = get_cpu_name()
cpu_memory = get_cpu_memory_usage()
# 获取GPU信息
gpu_data = get_gpu_info()
# 初始化信息文本
info_text = f"CPU名称: {cpu_name}\n"
info_text += f"CPU使用率: {cpu_usage}%\n"
info_text += f"CPU内存使用: {cpu_memory['used_memory']} / {cpu_memory['total_memory']}\n"
# 构造GPU信息的显示文本
for gpu in gpu_data:
info_text += (f"GPU {gpu['id']} ({gpu['name']}):\n"
f" 使用率: {gpu['load']}\n"
f" 温度: {gpu['temp']}\n"
f" 内存使用: {gpu['used_memory']} / {gpu['total_memory']}\n")
# 更新GUI中的文本
label.config(text=info_text)
# 设置定时器,每3秒更新一次信息
root.after(3000, update_info)
# 启动 .NET 程序而不显示命令行窗口
subprocess.Popen(NET_PROGRAM_PATH, shell=False, creationflags=subprocess.CREATE_NO_WINDOW)
# 创建主窗口
root = tk.Tk()
root.title("CPU和GPU信息") # 设置窗口标题
# 创建标签组件,用于显示信息
label = tk.Label(root, text="", justify=tk.LEFT)
label.pack(padx=20, pady=20) # 设置填充
# 调用update_info进行首次信息更新
update_info()
# 进入消息循环
root.mainloop()
下载地址:
https://openhardwaremonitor.org/downloads/
编写.NET程序
可以利用VS2019来编写程序。
using System; // 引入系统命名空间,用于基本类型和控制台操作
using OpenHardwareMonitor.Hardware; // 引入硬件监控库命名空间
class Program
{
static void Main(string[] args) // 主函数,程序入口点
{
Computer computer = new Computer { CPUEnabled = true }; // 创建Computer对象,启用CPU监测
computer.Open(); // 开启硬件监控
try
{
while (true) // 无限循环,直到收到退出信号
{
foreach (var hardware in computer.Hardware) // 遍历所有硬件
{
hardware.Update(); // 更新硬件信息
Console.WriteLine($"检测到 {hardware.HardwareType}: {hardware.Name}"); // 打印硬件类型和名称
foreach (var sensor in hardware.Sensors) // 遍历硬件上的传感器
{
if (sensor.SensorType == SensorType.Temperature) // 检查传感器类型是否为温度
{
if (sensor.Value.HasValue) // 检查温度值是否存在
{
Console.WriteLine($"传感器名称: {sensor.Name}, 温度值: {sensor.Value.Value}°C"); // 打印传感器名称和温度值
}
else // 如果温度值不存在
{
Console.WriteLine($"传感器名称: {sensor.Name}, 温度值: 无法获取"); // 打印传感器名称和提示信息
}
}
}
}
Thread.Sleep(3000); // 每3秒执行一次
}
}
catch (Exception ex) // 捕获并处理异常
{
Console.WriteLine($"出现错误: {ex.Message}"); // 打印错误信息
}
finally
{
computer.Close(); // 关闭硬件监控
}
//Console.WriteLine("程序完成。按任意键退出。"); // 提示用户程序完成
//Console.ReadKey(); // 等待用户按键
}
}
代码运行的结果:
图三
完成代码编写之后,然后发布程序。
图四
发布的程序,只需要注意发布到哪个文件夹就行了,其他可以默认。在主体程序中,一定要注意你的.NET程序发布的名称,并且一定要注意用管理员身份才能获取温度信息,因此打开主体程序一定要用管理员身份运行。还有一点就是需要将OpenHardwareMonitor软件的文件与发布的程序放到同一个文件夹下面。
注意:使用了GUI界面,但是不要关闭命令提示符的界面,不然就关闭了代码运行,应当等待GUI界面出现后才可以关闭。
呈现结果:
图五