您现在的位置是:首页 >技术教程 >Python 获取windows下硬件数据信息(CPU,内存,英特尔、英伟达、AMD显卡使用率及详细信息)网站首页技术教程

Python 获取windows下硬件数据信息(CPU,内存,英特尔、英伟达、AMD显卡使用率及详细信息)

手速极快的点狗 2024-06-14 17:17:26
简介Python 获取windows下硬件数据信息(CPU,内存,英特尔、英伟达、AMD显卡使用率及详细信息)

前言:最近一直在做关于显卡数据采集的调研工作,也在github上看到了一些三方库比如Python和golang的psutil, python: gpustart,再或者通过wmi或者windowsApi等底层接口 但是都只能获取到显卡的名称以及厂家信息等 无法真正意义上获取到显卡占用率等数据 在或者只能获取到英伟达的显卡数据 (该数据都是通过英伟达所开放出来的命令工具所获取到的) 后通过阅读C++ 的一个windows插件 发现他在底层使用了一个叫openhardwaremonitor的动态库 后开始尝试
结果:
在这里插入图片描述
虽然可以在win系统上获取到amd和英伟达以及英特尔显卡的使用率 但是并不准确

结果虽然差强人意,但是起码指明了一道方向 后来通过github上查看该项目的描述时得知 该动态库是从另外一个库中迁移出来的分支 LibreHardwareMonitor

LibreHardwareMonitor
下载地址:下载LibreHardwareMonitor.dll
一个C#实线的可与底层系统进行交互的动态库
2.7start 被众多插件软件所引用
在这里插入图片描述C#语言的动态库,那么在python中如何使用?
pythonnet (一个用python解析.net的三方库 实现了.dll文件的动态引用功能)
安装: pip install pythonnet
使用:

```python
 import clr  # pythonnet 
 clr.AddReference(dll)# 加载dll动态库
 # 将需要使用的动态库通过 from import进行导入(因libreHardwareMonitor.lib没有文档 所以按照这种导入即可)
 from LibreHardwareMonitor.Hardware import Computer
 computer = Computer() # 正常实例化即可
```

我们如何知道LibreHardwareMonitor的参数都有哪些呢? 可以通过github上的描述进行查看 这是一个c#的示例
在这里插入图片描述
通过该示例 我们可以看到 关于computer初始化完成后有几个属性 可以控制当前.dll动态库对哪些数据进行获取
本次只对该3个参数进行使用, 感兴趣的可以去尝试一下另外4个参数
1. IsCpuEnabled 布尔值 获取CPU时为true
2. IsGpuEnabled 布尔值 获取GPU时为true
3. IsMemoryEnabled 布尔值 获取内存时为true
使用:

import clr
import os, sys
clr.AddReference(path + './LibreHardwareMonitorLib') # 这里不需要加后缀.dll 内部会自动拼接
from LibreHardwareMonitor.Hardware import Computer

computer_tmp = Computer()  # 实例这这个类
# computer_tmp.IsCpuEnabled = True  # 获取CPU时用
computer_tmp.IsGpuEnabled = True  # 获取GPU时用
# computer_tmp.IsMemoryEnabled = True  # 获取内存时用
# self.computer_tmp.IsNetworkEnabled = True  # 获取网卡数据时使用
computer_tmp.Open()

print(len(computer_tmp.Hardware))

for computer in computer_tmp.Hardware:
    computer.Update()
    data_dict = []
    for s in computer.Sensors:
        print("名称为:", s.Name)
        # print("元器件名称:", s.Identifier)
        print("类型为:", s.SensorType)
        print("值是:", s.Value)
        sensor_type = str(s.SensorType)

        if sensor_type == "Load":
            data_dict.append({
                str(s.Name).replace("D3D ", ""): s.Value
            })
    print(data_dict)

结果:
在这里插入图片描述
参数:
Hardware:对应python中的列表 对应的是Computer中为true的属性值
Hardware[index].Sensors : 对应的是获取到的具体数据
属性:
Name: 元器件名称
Identifier:资源标识符
SensorType:硬件类型 想起查看下方描述
Parent: 所属父级元器件
Hardware[index].Sensors.SensorType:当前获取到的数据类型(如果存在则显示)
在这里插入图片描述
具体实现:
FastApi: 异步web开发框架,提供api访问
pythonnet: 访问.dll文件获取底层交互能力
psutil: 获取内存的具体使用(LibreHardwareMonitor只提供了负载值 未提供对应的总内存以及使用内存的详细值)

完整代码main.py

import uvicorn
from fastapi import FastAPI, APIRouter
from fastapi.middleware.cors import CORSMiddleware
import clr
import yaml, os, sys
import psutil
from starlette.responses import JSONResponse

sys.path.append(os.getcwd())

app = FastAPI(title="设备信息获取",
              description="用于获取windows下显卡,内存,cpu,网卡等使用情况",
              version="v0.1")


class GetDeviceInfo:

    def __init__(self, dll: str):

        clr.AddReference(dll)
        from LibreHardwareMonitor.Hardware import Computer
        self.computer_tmp = Computer()  # 实例这这个类
        self.computer_tmp.IsCpuEnabled = True  # 获取CPU温度时用
        self.computer_tmp.IsGpuEnabled = True  # 获取GPU温度时用
        self.computer_tmp.IsMemoryEnabled = True  # 获取内存时用
        # self.computer_tmp.IsNetworkEnabled = True  # 获取网卡时用
        self.computer_tmp.Open()

    @staticmethod
    def memory_info()->tuple:
        p = psutil.virtual_memory()
        return p.total / 1024 / 1024, p.used / 1024 / 1024

    def params_hardware(self, index: int) -> dict:
        hard = self.computer_tmp.Hardware[index]
        hard.Update()
        device_data = {}

        for i in hard.Sensors:
            sensor_type = str(i.SensorType)
            if sensor_type == "Load" and sensor_type not in device_data:
                device_data["Name"] = hard.Name
                device_data["Load"] = i.Value
            if index == 2 and "/temperature" in str(i.Identifier):
                device_data["temperature"] = i.Value
            if sensor_type == "Load" and index == 2:
                device_data[str(i.Name).replace("D3D ", "")] = i.Value
        if index == 1:
            total, used = self.memory_info()
            device_data['total'] = total
            device_data['used'] = used
        return device_data

    def run(self):
        data_list = []
        type_list = ["CPU", "memory", "GPU"]
        com_len = len(self.computer_tmp.Hardware)
        if com_len > len(type_list):
            number = com_len - len(type_list)
            [type_list.append("other" + str(i)) for i in range(number)]
        for index in range(com_len):
            device_info = self.params_hardware(index)
            device_info['type'] = type_list[index]
            data_list.append(device_info)
        return data_list


class Router:
    routerApi = APIRouter()

    def __init__(self):
    	# 如果使用Pyinstaller -F 进行编译时,将这里放开, 解决相对路径下找不到可用的.dll文件问题
        # path = os.path.dirname(sys.executable)
        # self.device = GetDeviceInfo(path + "/lib/LibreHardwareMonitorLib")
		
		self.device = GetDeviceInfo("./lib/LibreHardwareMonitorLib")
    async def get_device_info(self):
        return JSONResponse(
            status_code=200,
            content={
                "message": "success!",
                "code": 200,
                "data": self.device.run()
            }
        )

    def router_list(self):
        self.routerApi.add_api_route("/deviceInfo", self.get_device_info, methods=["GET"])


def init_service():
	# 处理浏览器请求时会出现跨域情况
    app.add_middleware(CORSMiddleware,
                       allow_origins="*",
                       allow_credentials=True,
                       allow_methods=["*"],
                       allow_headers=["*"], )
    router = Router()
    router.router_list()
    app.include_router(router.routerApi, prefix="/device")


init_service()
if __name__ == '__main__':
	# 也可通过配置文件配置相关启动的host以及域名
    #with open("config/config.yaml", mode='r+', encoding='utf-8') as f:
       # data = yaml.load(f.read(), Loader=yaml.Loader)
    uvicorn.run("__main__:app", host="0.0.0.0", port=9969)

接口:
GET http://localhost:9969/device/deviceInfo
结果:
在这里插入图片描述
该服务可直接运行 也可编译后通过.exe进行运行 当前仅支持windows下 暂未支持linux以及mac
已上传至https://github.com/yuanhuihui1203/GetDeviceInfo 各位大佬可以点击一下start支持!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。