Python获取CPU/GPU温度
根据psutil官方文档
psutil.sensors_temperatures()不提供在Windows下获取CPU温度的功能。原因是操作系统并未内置,而CPU/GPU/主板等传感器各厂商实现方法不统一(所以诸如HWInfo之类的软件做了更多的工作才得以实现)。
查了网上的资料,简单的实现方法是安装三方监控软件,再通过python调用该监控软件的方式来实现获取温度。
- Open Hardware Monitor,然而可惜的是,该软件已经5年没更新了。
- LibreHardwareMonitor(以下简称LHM),它是前者的fork并且一直在维护中。Python使用它有几种方案:
- DLL调用:反应很慢,好几秒才能得到返回值,且必须以管理员运行;
- 解析其Web Server页面,但也不是最优解;
- 另有其他方案若干,抄来抄去的,有的甚至跑不通。
经过探索验证,找到一种较好的方法。当然,这个方法吃相也不太好看(但解决了问题)。
首先用图说话:
讲解思路:安装了LHM后,它有个功能是可以开启一个Web服务,默认地址为
在Options –> Remote Web Server –> Run打勾后,访问上述URL可访问网页版的硬件监控数据,如图所示:
有了它,自然想到抓网页,这对Python来说也容易。当然它不漂亮。有聪明人发现这个Web服务其实有一个JSON格式的入口:
数据返回如下:
太好了!解析JSON结构就可以得到我们想要的数据。
然而,这个/data.json返回了很多数据,而不仅仅是传感器温度。
这份数据量也不小,解析速度还是不够理想。
有没有更好的方式呢?
经查看LHM的源码,发现它有另外一个未公布的URL:
它的返回值也是JSON数据,且是/data.json服务的子集。
传入id,它只返回最精简的数据,如下图:
是不是很棒了?!其中{xxx}就是/data.json中已经给出的对应SensorId,如下图:
所以,对于某台固定的电脑,先访问/data.json,找到想要的那一条温度,记下它的SensorId,接下来就简单了。示例代码如下:
import psutil,requests
class ExHWInfo:
def __init__(self, web_addr="http://localhost:8085/Sensor?action=Get",cpu_node_id="/intelcpu/0/temperature/1"):
self.web_addr=web_addr
self.cpu_node_id=cpu_node_id
def cpu_temperature(self):
if hasattr(psutil, "sensors_temperatures"): # May be Linux
temps = psutil.sensors_temperatures()
if not temps:
return None
return temps[0].current
else: # May be windows, let's read info from http via LibreHardwareMonitor
url = '{}&id={}'.format(self.web_addr,self.cpu_node_id)
try:
response = requests.get(url)
response.raise_for_status()
ret=response.json()
return int(ret["value"])
except requests.exceptions.HTTPError as err:
print(err)
return None
总结:
- 优点:返回速度快,且不必以管理员运行python(dll调用则需要);
- 缺点:每台机器都要提前找到SensorId并且hardcode,另外LHM像是外挂,不够优雅。
P.S. /Sensor这个服务不要传错参数,一旦id不存在或者其他参数有误,会直接导致LHM软件崩溃。若有生产环境需求,建议修改LHW源码,加上判断逻辑,以提升稳定性。
参考资料
https://github.com/LibreHardwareMonitor/LibreHardwareMonitor/discussions/677
https://github.com/snip3rnick/PyHardwareMonitor
https://github.com/Cyril-Meyer/PyHardwareMonitor