Python获取CPU/GPU温度

根据psutil官方文档

https://psutil.readthedocs.io/en/latest/

psutil.sensors_temperatures()不提供在Windows下获取CPU温度的功能。原因是操作系统并未内置,而CPU/GPU/主板等传感器各厂商实现方法不统一(所以诸如HWInfo之类的软件做了更多的工作才得以实现)。

查了网上的资料,简单的实现方法是安装三方监控软件,再通过python调用该监控软件的方式来实现获取温度。

  • Open Hardware Monitor,然而可惜的是,该软件已经5年没更新了。
  • LibreHardwareMonitor(以下简称LHM),它是前者的fork并且一直在维护中。Python使用它有几种方案:
    • DLL调用:反应很慢,好几秒才能得到返回值,且必须以管理员运行;
    • 解析其Web Server页面,但也不是最优解;
    • 另有其他方案若干,抄来抄去的,有的甚至跑不通。

经过探索验证,找到一种较好的方法。当然,这个方法吃相也不太好看(但解决了问题)。


首先用图说话:
原理图


讲解思路:安装了LHM后,它有个功能是可以开启一个Web服务,默认地址为

http://localhost:8085/

在Options –> Remote Web Server –> Run打勾后,访问上述URL可访问网页版的硬件监控数据,如图所示:
页面数据示例


有了它,自然想到抓网页,这对Python来说也容易。当然它不漂亮。有聪明人发现这个Web服务其实有一个JSON格式的入口:

http://localhost:8085/data.json

数据返回如下:
data.json数据示例

太好了!解析JSON结构就可以得到我们想要的数据。
然而,这个/data.json返回了很多数据,而不仅仅是传感器温度。
这份数据量也不小,解析速度还是不够理想。
有没有更好的方式呢?


经查看LHM的源码,发现它有另外一个未公布的URL:

http://localhost:8085/Sensor?action=Get&id={xxx}

它的返回值也是JSON数据,且是/data.json服务的子集。
传入id,它只返回最精简的数据,如下图:
Sensor数据示例


是不是很棒了?!其中{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