簡體   English   中英

在python中訪問CPU溫度

[英]Accessing CPU temperature in python

我需要一個在 python 中訪問 CPU 溫度的示例代碼。

我正在運行 Windows 7,順便說一句。

使用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)

下載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()如果需要,還運行SubHardware[x].Update() )。

您可以使用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。

我從第 3 方收到了一個 C++ 項目,並找到了如何使用 C++ 獲取 CPU 和 Board Temp。 然后我發現了這個,我用來幫助我用 ctypes 在 python 中模擬 C++ 函數,很多代碼是直接從該存儲庫復制的。 '\\\\.\\AdvLmDev' 特定於我使用的 PC,應替換為 '\\\\.\\PhysicalDrive0'。 還有一個功能可以獲取其他 CPU 功率測量值。 我這樣做是因為我不想使用 Open Hardware Monitor。 您可能必須以管理員身份運行代碼才能使其工作。

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

查看cputemp庫。

編輯:在 Windows 上,您可以使用 python WMI 庫轉換這個使用 WMI 的IronPython 腳本

我使用了https://github.com/BennyCarbajal/PyTherm 中的實用程序

幾乎安裝pythonnet:

pip install pythonnet

然后只需以管理員身份執行終端,最后執行文件:

python pytherm.py

如果您以普通用戶身份運行它,它也可以工作,但不會輸出盡可能多的數據。

由於它以 JSON 格式返回數據,因此您應該很容易獲取您正在尋找的特定硬件的數據。

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”子句的艱難方法,所以我不得不做一些花哨的字符串格式來獲得正確的順序,因為查詢以相反的順序返回核心。 這讓我有點困惑,直到我設計出這種方式來解決它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM