我需要一个在 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 和主板温度。然后我发现了 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
查看 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”子句,因此我必须执行一些奇特的字符串格式才能使顺序正确,因为查询以相反的顺序返回核心。这让我有点困惑,直到我设计了这种方法。
对于那些尝试在 Windows 操作系统上使用 python 运行 OpenHardwareMonitor 时遇到问题的人,这两种解决方案都无法帮助我,即使我在管理员提示符下运行它(是的,我们需要使用管理员权限运行它,但这对我来说还不够) .
对我来说修复的是卸载 python 并使用“所有用户”选项再次安装它(以便管理员帐户可以使用 python)。然后OpenHardwareLib.dll终于加载成功了。