我需要一个在 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()
如果需要)。
您可以使用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 library转换这个使用 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”子句的困难方式,所以我必须做一些花哨的字符串格式来获得正确的顺序,因为查询以相反的顺序返回核心。这让我有点困惑,直到我设计了这个方法。