在Python中访问CPU温度

问题描述 投票:0回答:8

我需要一个在 python 中访问 CPU 温度的示例代码。

顺便说一句,我正在运行 Windows 7。

python windows cpu temperature
8个回答
20
投票

使用 WMI 模块 + 打开硬件监视器 + 此处描述的 WMI 接口

示例代码:

import wmi
w = wmi.WMI(namespace="root\OpenHardwareMonitor")
temperature_infos = w.Sensor()
for sensor in temperature_infos:
    if sensor.SensorType==u'Temperature':
        print(sensor.Name)
        print(sensor.Value)

18
投票

下载 http://openhardwaremonitor.org/downloads/http://www.cputhermometer.com/ 并解压 OpenHardwareMonitorLib.dll 和 CPUThermometerLib.dll 并将它们放在一个目录中。

然后,您可以使用 pythonnet 模块来寻址 .dll 并提取这些程序提供的任何统计信息。 cputhermometer 提供每个核心的 CPU 温度,openhardwaremonitor 提供其他一切。无需使用 WMI,这需要程序在后台处于活动状态。

我编写了一个小脚本(python 3.6.5)来显示系统上可用的每个温度传感器,您当然可以轻松地将其修改为其他传感器类型。您必须以管理员身份运行此程序:

import clr #package pythonnet, not clr


openhardwaremonitor_hwtypes = ['Mainboard','SuperIO','CPU','RAM','GpuNvidia','GpuAti','TBalancer','Heatmaster','HDD']
cputhermometer_hwtypes = ['Mainboard','SuperIO','CPU','GpuNvidia','GpuAti','TBalancer','Heatmaster','HDD']
openhardwaremonitor_sensortypes = ['Voltage','Clock','Temperature','Load','Fan','Flow','Control','Level','Factor','Power','Data','SmallData']
cputhermometer_sensortypes = ['Voltage','Clock','Temperature','Load','Fan','Flow','Control','Level']


def initialize_openhardwaremonitor():
    file = 'OpenHardwareMonitorLib.dll'
    clr.AddReference(file)

    from OpenHardwareMonitor import Hardware

    handle = Hardware.Computer()
    handle.MainboardEnabled = True
    handle.CPUEnabled = True
    handle.RAMEnabled = True
    handle.GPUEnabled = True
    handle.HDDEnabled = True
    handle.Open()
    return handle

def initialize_cputhermometer():
    file = 'CPUThermometerLib.dll'
    clr.AddReference(file)

    from CPUThermometer import Hardware
    handle = Hardware.Computer()
    handle.CPUEnabled = True
    handle.Open()
    return handle

def fetch_stats(handle):
    for i in handle.Hardware:
        i.Update()
        for sensor in i.Sensors:
            parse_sensor(sensor)
        for j in i.SubHardware:
            j.Update()
            for subsensor in j.Sensors:
                parse_sensor(subsensor)


def parse_sensor(sensor):
        if sensor.Value is not None:
            if type(sensor).__module__ == 'CPUThermometer.Hardware':
                sensortypes = cputhermometer_sensortypes
                hardwaretypes = cputhermometer_hwtypes
            elif type(sensor).__module__ == 'OpenHardwareMonitor.Hardware':
                sensortypes = openhardwaremonitor_sensortypes
                hardwaretypes = openhardwaremonitor_hwtypes
            else:
                return

            if sensor.SensorType == sensortypes.index('Temperature'):
                print(u"%s %s Temperature Sensor #%i %s - %s\u00B0C" % (hardwaretypes[sensor.Hardware.HardwareType], sensor.Hardware.Name, sensor.Index, sensor.Name, sensor.Value))

if __name__ == "__main__":
    print("OpenHardwareMonitor:")
    HardwareHandle = initialize_openhardwaremonitor()
    fetch_stats(HardwareHandle)
    print("\nCPUMonitor:")
    CPUHandle = initialize_cputhermometer()
    fetch_stats(CPUHandle)

这是我系统上的输出:

OpenHardwareMonitor:
SuperIO Nuvoton NCT6791D Temperature Sensor #0 CPU Core - 42.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #1 Temperature #1 - 35.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #2 Temperature #2 - 34.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #3 Temperature #3 - 25.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #4 Temperature #4 - 101.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #5 Temperature #5 - 16.0°C
SuperIO Nuvoton NCT6791D Temperature Sensor #6 Temperature #6 - 14.0°C
GpuNvidia NVIDIA GeForce GTX 1070 Temperature Sensor #0 GPU Core - 60.0°C
HDD ST31000528AS Temperature Sensor #0 Temperature - 37.0°C
HDD WDC WD20EARX-00PASB0 Temperature Sensor #0 Temperature - 36.0°C
HDD WDC WDS100T2B0B-00YS70 Temperature Sensor #0 Temperature - 40.0°C
HDD WDC WD80EFZX-68UW8N0 Temperature Sensor #0 Temperature - 31.0°C
HDD WDC WD30EFRX-68EUZN0 Temperature Sensor #0 Temperature - 30.0°C
HDD WDC WD80EFZX-68UW8N0 Temperature Sensor #0 Temperature - 33.0°C
HDD Crucial_CT256MX100SSD1 Temperature Sensor #0 Temperature - 40.0°C

CPUMonitor:
CPU Intel Core i7-8700K Temperature Sensor #0 CPU Core #1 - 39.0°C
CPU Intel Core i7-8700K Temperature Sensor #1 CPU Core #2 - 38.0°C
CPU Intel Core i7-8700K Temperature Sensor #2 CPU Core #3 - 37.0°C
CPU Intel Core i7-8700K Temperature Sensor #3 CPU Core #4 - 41.0°C
CPU Intel Core i7-8700K Temperature Sensor #4 CPU Core #5 - 36.0°C
CPU Intel Core i7-8700K Temperature Sensor #5 CPU Core #6 - 47.0°C

有关更多文档(但是您应该能够从上面的代码推断出您需要的所有内容),请参阅 https://github.com/openhardwaremonitor/openhardwaremonitor/(或 cputhermometer,在网站上)源代码,当您使用 python 时,函数和方法是相同的。

我尚未在任何其他计算机上对此进行测试,因此不同的处理器架构的功能可能不相同。

确保在两次测量之间运行

Hardware[x].Update()
(如果需要,还运行
SubHardware[x].Update()
)。


6
投票

您可以使用 pywin32 访问本机 Windows API。我相信如果主板驱动程序的制造商通过他们的驱动程序注册了 WMI 数据提供程序,应该可以查询 Windows API 来获取 CPU 温度。假设是这种情况,您可以下载 ars 答案中提到的 pywin32 扩展Python WMI 模块,然后按以下步骤操作:

import wmi
w = wmi.WMI()
print w.Win32_TemperatureProbe()[0].CurrentReading

查看ars答案中的IronPython脚本,似乎还有另一种方法可以做到这一点,即使用不同的WMI对象。使用相同的 API 和方法,您可以尝试使用

接收温度值
w = wmi.WMI(namespace="root\wmi")
temperature_info = w.MSAcpi_ThermalZoneTemperature()[0]
print temperature_info.CurrentTemperature

显然应该返回十分之一开尔文的温度值,因此要获得摄氏度,我猜你只需将该值除以 10 并减去 ~273。


5
投票

我从第 3 方收到了一个 C++ 项目,并找到了如何使用 C++ 获取 CPU 和主板温度。然后我发现了 this,我用它来帮助我用 ctypes 模仿 python 中的 C++ 函数,很多代码都是直接从该存储库复制的。 “\.\AdvLmDev”特定于我使用的 PC,应替换为“\.\PhysicalDrive0”。还有一个功能可以获取其他 CPU 功率测量值。我这样做是因为我不想使用开放硬件监视器。您可能必须以管理员身份运行代码才能正常工作。

import ctypes
import ctypes.wintypes as wintypes
from ctypes import windll


LPDWORD = ctypes.POINTER(wintypes.DWORD)
LPOVERLAPPED = wintypes.LPVOID
LPSECURITY_ATTRIBUTES = wintypes.LPVOID

GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000

FILE_SHARE_WRITE=0x00000004
ZERO=0x00000000

CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5

FILE_ATTRIBUTE_NORMAL = 0x00000080

INVALID_HANDLE_VALUE = -1
FILE_DEVICE_UNKNOWN=0x00000022
METHOD_BUFFERED=0
FUNC=0x900
FILE_WRITE_ACCESS=0x002

NULL = 0
FALSE = wintypes.BOOL(0)
TRUE = wintypes.BOOL(1)


def CTL_CODE(DeviceType, Function, Method, Access): return (DeviceType << 16) | (Access << 14) | (Function <<2) | Method




def _CreateFile(filename, access, mode, creation, flags):
    """See: CreateFile function http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).asp """
    CreateFile_Fn = windll.kernel32.CreateFileW
    CreateFile_Fn.argtypes = [
            wintypes.LPWSTR,                    # _In_          LPCTSTR lpFileName
            wintypes.DWORD,                     # _In_          DWORD dwDesiredAccess
            wintypes.DWORD,                     # _In_          DWORD dwShareMode
            LPSECURITY_ATTRIBUTES,              # _In_opt_      LPSECURITY_ATTRIBUTES lpSecurityAttributes
            wintypes.DWORD,                     # _In_          DWORD dwCreationDisposition
            wintypes.DWORD,                     # _In_          DWORD dwFlagsAndAttributes
            wintypes.HANDLE]                    # _In_opt_      HANDLE hTemplateFile
    CreateFile_Fn.restype = wintypes.HANDLE

    return wintypes.HANDLE(CreateFile_Fn(filename,
                         access,
                         mode,
                         NULL,
                         creation,
                         flags,
                         NULL))


handle=_CreateFile('\\\\.\\AdvLmDev',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)

def _DeviceIoControl(devhandle, ioctl, inbuf, inbufsiz, outbuf, outbufsiz):
    """See: DeviceIoControl function
http://msdn.microsoft.com/en-us/library/aa363216(v=vs.85).aspx
"""
    DeviceIoControl_Fn = windll.kernel32.DeviceIoControl
    DeviceIoControl_Fn.argtypes = [
            wintypes.HANDLE,                    # _In_          HANDLE hDevice
            wintypes.DWORD,                     # _In_          DWORD dwIoControlCode
            wintypes.LPVOID,                    # _In_opt_      LPVOID lpInBuffer
            wintypes.DWORD,                     # _In_          DWORD nInBufferSize
            wintypes.LPVOID,                    # _Out_opt_     LPVOID lpOutBuffer
            wintypes.DWORD,                     # _In_          DWORD nOutBufferSize
            LPDWORD,                            # _Out_opt_     LPDWORD lpBytesReturned
            LPOVERLAPPED]                       # _Inout_opt_   LPOVERLAPPED lpOverlapped
    DeviceIoControl_Fn.restype = wintypes.BOOL

    # allocate a DWORD, and take its reference
    dwBytesReturned = wintypes.DWORD(0)
    lpBytesReturned = ctypes.byref(dwBytesReturned)

    status = DeviceIoControl_Fn(devhandle,
                  ioctl,
                  inbuf,
                  inbufsiz,
                  outbuf,
                  outbufsiz,
                  lpBytesReturned,
                  NULL)

    return status, dwBytesReturned

class OUTPUT_temp(ctypes.Structure):
        """See: http://msdn.microsoft.com/en-us/library/aa363972(v=vs.85).aspx"""
        _fields_ = [
                ('Board Temp', wintypes.DWORD),
                ('CPU Temp', wintypes.DWORD),
                ('Board Temp2', wintypes.DWORD),
                ('temp4', wintypes.DWORD),
                ('temp5', wintypes.DWORD)
                ]

class OUTPUT_volt(ctypes.Structure):
        """See: http://msdn.microsoft.com/en-us/library/aa363972(v=vs.85).aspx"""
        _fields_ = [
                ('VCore', wintypes.DWORD),
                ('V(in2)', wintypes.DWORD),
                ('3.3V', wintypes.DWORD),
                ('5.0V', wintypes.DWORD),
                ('temp5', wintypes.DWORD)
                ]

def get_temperature():
    FUNC=0x900
    outDict={}

    ioclt=CTL_CODE(FILE_DEVICE_UNKNOWN, FUNC, METHOD_BUFFERED, FILE_WRITE_ACCESS)

    handle=_CreateFile('\\\\.\\AdvLmDev',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)

    win_list = OUTPUT_temp()
    p_win_list = ctypes.pointer(win_list)
    SIZE=ctypes.sizeof(OUTPUT_temp)


    status, output = _DeviceIoControl(handle, ioclt , NULL, ZERO, p_win_list, SIZE)


    for field, typ in win_list._fields_:
                #print ('%s=%d' % (field, getattr(disk_geometry, field)))
                outDict[field]=getattr(win_list,field)
    return outDict

def get_voltages():
    FUNC=0x901
    outDict={}

    ioclt=CTL_CODE(FILE_DEVICE_UNKNOWN, FUNC, METHOD_BUFFERED, FILE_WRITE_ACCESS)

    handle=_CreateFile('\\\\.\\AdvLmDev',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)

    win_list = OUTPUT_volt()
    p_win_list = ctypes.pointer(win_list)
    SIZE=ctypes.sizeof(OUTPUT_volt)


    status, output = _DeviceIoControl(handle, ioclt , NULL, ZERO, p_win_list, SIZE)


    for field, typ in win_list._fields_:
                #print ('%s=%d' % (field, getattr(disk_geometry, field)))
                outDict[field]=getattr(win_list,field)
    return outDict

3
投票

查看 cputemp 库。

编辑:在 Windows 上,您也许可以使用 python WMI 库来转换使用 WMI 的 IronPython 脚本


3
投票

我使用了来自 https://github.com/BennyCarbajal/PyTherm

的实用程序

几乎安装 pythonnet:

pip install pythonnet

然后以管理员身份执行终端即可,最后执行文件:

python pytherm.py

如果您以普通用户身份运行它,它也可以工作,但不会输出那么多数据。

由于它以 JSON 格式返回数据,因此您应该可以轻松获取您正在寻找的特定硬件的数据。


0
投票

eadmaster 提供的代码可能适用于 OpenHardwareMonitor 已编程的较旧 CPU,但我有 Skylake i7 6700K CPU。 OpenHardwareMonitor 没有为我提供任何结果。然而,这个程序有一个分支,称为 CPU Thermometer,它基于 OpenHardwareMonitor,它确实 可以识别我的 CPU。

在寻找如何通过 Python 获取 CPU 温度的过程中,我切换到了 IronPython,以便能够访问 .Net 框架并轻松访问其他性能数据,但应该很容易弄清楚如何对其进行改造vanilla Python 2.7(只需运行 CPU Thermometer 而不是 OpenHardwareMonitor 并将命名空间更改为“root\CPUThermometer”?就这么简单吗?)。

#
# CPU Temp --REQUIRES CPU TEMPERATURE TO BE RUNNING!--
#
import clr
clr.AddReference('System.Management')
from System.Management import (ManagementScope, ManagementObject, ManagementObjectSearcher, WqlObjectQuery)

scope = ManagementScope("root\CPUThermometer")

searcher = ManagementObjectSearcher(scope, 
    WqlObjectQuery("SELECT * FROM Sensor Where SensorType LIKE 'Temperature'"), None)

mo = ManagementObject()

print "\n"
print "              Temp      Min       Max"

strout = str(' ')

for mo in searcher.Get():
    strout = '{0}   {1} C    {2} C    {3} C\n{4}'.format(mo["Name"], mo["Value"], mo["Min"], mo["Max"], strout)

print strout

示例输出:

D:\IronPython 2.7>ipy64 c:\users\neamerjell\desktop\test.py


              Temp      Min       Max
CPU Core #1   21.0 C    20.0 C    37.0 C
CPU Core #2   23.0 C    21.0 C    39.0 C
CPU Core #3   21.0 C    20.0 C    32.0 C
CPU Core #4   21.0 C    20.0 C    36.0 C

我发现查询不是很标准的 SQL 并且不喜欢“Order By”子句,因此我必须执行一些奇特的字符串格式才能使顺序正确,因为查询以相反的顺序返回核心。这让我有点困惑,直到我设计了这种方法。


0
投票

对于那些尝试在 Windows 操作系统上使用 python 运行 OpenHardwareMonitor 时遇到问题的人,这两种解决方案都无法帮助我,即使我在管理员提示符下运行它(是的,我们需要使用管理员权限运行它,但这对我来说还不够) .

对我来说修复的是卸载 python 并使用“所有用户”选项再次安装它(以便管理员帐户可以使用 python)。然后OpenHardwareLib.dll终于加载成功了。

© www.soinside.com 2019 - 2024. All rights reserved.