python制作服务器信息监控的api,支持多平台,基于flask和socketio

system-info-api

python的系统信息web api。包括restful和socketio,以及获取系统硬件信息的函数。
这些接口方便绘制可视化图表

项目地址:https://github.com/Pure-Peace/system-info-api

支持windows,linux多平台

Python system information web api. Including restful and socketio, convenient to draw visual charts


说明

此项目包含基于flask的restful api以及socketio,分为两种方式提供服务。

  1. 系统信息:背景线程将会每间隔数秒更新系统信息(cpu、内存、硬盘、负载等),并在本地进行缓存,缓存形式包括json文件以及内存(变量)。
  2. 主动推送:每当背景线程更新系统信息,socketio将会广播这些系统信息数据。
  3. 被动获取:你可以通过访问web api来主动获取已经缓存的系统信息,这些缓存信息会随着背景线程的运行而更新。
也就是说,服务器监控页面只需要在首次加载的时候访问web api获取已缓存的(历史)系统信息一次,剩下的图表更新均由socketio进行推送数据更新。

省资源,而且实时性高。


文件分为三部分

main.py

包含背景线程以及flask、socketio。

'''
@author: Pure-Peace
@name: 系统信息
@time: 2020年8月17日
@version: 0.1
'''

import systemInfo
from utils import log, getTime

from gevent import monkey; monkey.patch_all()

import threading
import time
import json

from flask_socketio import SocketIO
from flask import Flask, jsonify, request
from flask_cors import CORS

# fix: windows cmd cannot display colors
from colorama import init
init(autoreset=True)


# initial(s)
app = Flask(__name__)
#app.config['SECRET_KEY'] = 'asdqwezxc'
app.config.update(RESTFUL_JSON=dict(ensure_ascii=False))
app.config["JSON_AS_ASCII"] = False

# 跨域
CORS(app)

socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*', async_mode='gevent')

class Cache:
    def __init__(self, name: str, limit: int = 30):
        '''
        缓存

        Parameters
        ----------
        name : str
            缓存名称,关系到文件保存.
        limit : int, optional
            缓存上限,最高存储多少条信息. The default is 30.

        Returns
        -------
        None.

        '''
        self.name = name
        self.limit = limit
        self.read()

    def add(self, item):
        '''
        添加数据到缓存中

        Parameters
        ----------
        item : TYPE
            DESCRIPTION.

        Returns
        -------
        None.

        '''
        if len(self.data) >= self.limit: del(self.data[0])
        self.data.append(item)
        self.save()

    def save(self):
        '''
        将缓存持久化,存储到name对应的json文件中

        Returns
        -------
        None.

        '''
        try:
            with open(f'{self.name}.json', 'w', encoding='utf-8') as file:
                json.dump(self.data, file, indent=4)
        except:
            pass

    def read(self):
        '''
        读取缓存(如果有)

        Returns
        -------
        None.

        '''
        try:
            with open(f'{self.name}.json', 'r', encoding='utf-8') as file:
                self.data = json.load(file)
        except:
            self.data = []


# apis -------------------------------

@app.route('/')
def root():
    return jsonify({
    
    'status': 1, 'message': 'hello'})

@app.route('/cpu_constants')
def cpuConstants():
    return jsonify(cpuData)

@app.route('/cpu_info')
def cpuInfo():
    return jsonify(cpuCache.data)

@app.route('/io_info')
def ioInfo():
    return jsonify(ioCache.data)

@app.route('/mem_info')
def memInfo():
    return jsonify(memCache.data)

@app.route('/network_info')
def networkInfo():
    return jsonify(networkCache.data)

@app.route('/load_info')
def loadInfo():
    return jsonify(loadCache.data)

# socketio -------------------------------

@socketio.on('disconnect')
def sioDisconnect():
    log('socketio连接断开:', request.remote_addr)

@socketio.on('connect')
def sioConnect():
    log('socketio连接建立:', request.remote_addr)

# 背景线程 -------------------------------

def cpuBackground(interval: int = 8) -> None:
    '''
    更新cpu信息并更新缓存,同时向前端socketio推送信息

    Parameters
    ----------
    interval : int, optional
        间隔多少时间更新一次cpu信息. The default is 8.

    Returns
    -------
    None
        DESCRIPTION.

    '''
    def task():
        data: dict = systemInfo.GetCpuInfo(constants = False) # 获取cpu信息
        cpuCache.add(data) # 更新缓存
        socketio.emit('update_cpu', data, broadcast=True) # 推送信息,事件名为update_cpu
    loopRun(task, interval) # 循环执行,每隔interval秒执行一次

def ioBackground(interval: int = 5) -> None:
    def task():
        data: dict = systemInfo.GetIoReadWrite()
        ioCache.add(data)
        socketio.emit('update_io', data, broadcast=True)
    loopRun(task, interval)

def memBackground(interval: int = 5) -> None:
    def task():
        data: dict = systemInfo.GetMemInfo()
        memCache.add(data)
        socketio.emit('update_mem', data, broadcast=True)
    loopRun(task, interval)

def networkBackground(interval: int = 5) -> None:
    def task():
        data: dict = systemInfo.GetNetWork()
        networkCache.add(data)
        socketio.emit('update_net', data, broadcast=True)
    loopRun(task, interval)

def loadBackground(interval: int = 5) -> None:
    def task():
        data: dict = systemInfo.GetLoadAverage()
        loadCache.add(data)
        socketio.emit('update_load', data, broadcast=True)
    loopRun(task, interval)

def loopRun(func, interval: int, *arg, **kwargs) -> None:
    '''
    循环执行

    Parameters
    ----------
    func : TYPE
        要执行的函数.
    interval : int
        间隔时间.
    *arg : TYPE
        位置参数.
    **kwargs : TYPE
        关键字参数.

    Returns
    -------
    None
        DESCRIPTION.

    '''
    while True:
        try:
            time.sleep(interval)
            func(*arg, **kwargs)
        except Exception as err:
            log('循环线程执行异常:', err)

# 线程列表
ts: list = [
      threading.Thread(target=cpuBackground),
      threading.Thread(target=ioBackground),
      threading.Thread(target=memBackground),
      threading.Thread(target=networkBackground),
      threading.Thread(target=loadBackground)
]

# 获取cpu常量信息
cpuData = systemInfo.cpuConstants.getDict

# 建立缓存
cpuCache = Cache('cpuInfo')
ioCache = Cache('ioInfo')
memCache = Cache('memInfo')
networkCache = Cache('networkInfo')
loadCache = Cache('loadInfo')
    
if __name__ == '__main__':
    # 开启所有线程
    for t in ts: t.start()
    
    log('应用已启动')
    # 启动app(危险:0.0.0.0将使得外网可直接访问)
    socketio.run(app, host = '0.0.0.0', port = 5678)

systemInfo.py

systemInfo.py模块中包含所有可用的系统信息函数(所有api可以在此处找到,包含一些说明)
项目地址:https://github.com/Pure-Peace/system-info

# -*- coding: utf-8 -*-
'''
@name: 系统信息 / SystemInfo
@author: PurePeace
@time: 2020年8月17日
@version: 0.1
'''

from typing import List, Dict, Any
from utils import log, getTime

import os
import time
import psutil
import platform
import hashlib
import re
import sys


from cachelib import SimpleCache
cache = SimpleCache()


UNIX: bool = os.name == 'posix'
SYS: str = platform.system()


class CpuConstants:
    def __init__(self):
        '''
        初始化CPU常量(多平台)

        Returns
        -------
        self.

        '''
        self.WMI = None
        self.initialed: bool = False
        self.cpuList: list = [] # windows only

        self.cpuCount: int = 0 # 物理cpu数量
        self.cpuCore: int = 0 # cpu物理核心数
        self.cpuThreads: int = 0 # cpu逻辑核心数
        self.cpuName: str = '' # cpu型号

        self.Update(True)


    def Update(self, update: bool = False) -> None:
        '''
        更新cpu数据

        Returns
        -------
        None.

        '''
        log('正在更新cpu常量...')
        if UNIX: self.GetCpuConstantsUnix(update)
        else: self.GetCpuConstantsWindows(update)
        log('更新完毕!')

        self.initialed: bool = True


    @property
    def getDict(self) -> Dict[int, str]:
        '''
        以字典格式获取当前cpu常量

        Returns
        -------
        Dict[int, str]
            DESCRIPTION.

        '''
        if not self.initialed: self.Update()
        return {
    
    
            'cpu_count': self.cpuCount,
            'cpu_name': self.cpuName,
            'cpu_core': self.cpuCore,
            'cpu_threads': self.cpuThreads
        }


    def GetCpuConstantsUnix(self, update: bool = False) -> None:
        '''
        获取unix下的cpu信息

        Parameters
        ----------
        update : bool, optional
            DESCRIPTION. The default is False.

        Returns
        -------
        None
            DESCRIPTION.

        '''
        if update or not self.initialed:
            ids: list = re.findall("physical id.+", readFile('/proc/cpuinfo'))

            # 物理cpu个数
            self.cpuCount: int = len(set(ids))

            # cpu型号(名称)
            self.cpuName: str = self.getCpuTypeUnix()


            self.GetCpuConstantsBoth()


    def InitWmi(self) -> None:
        '''
        初始化wmi(for windows)

        Returns
        -------
        None
            DESCRIPTION.

        '''
        import wmi
        self.WMI = wmi.WMI()


    def GetCpuConstantsBoth(self, update: bool = False) -> None:
        '''
        获取多平台共用的cpu信息

        Parameters
        ----------
        update : bool, optional
            强制更新数据. The default is False.

        Returns
        -------
        None
            DESCRIPTION.

        '''
        if update or not self.initialed:

            # cpu逻辑核心数
            self.cpuThreads: int = psutil.cpu_count()

            # cpu物理核心数
            self.cpuCore: int = psutil.cpu_count(logical=False)


    def GetCpuConstantsWindows(self, update: bool = False) -> None:
        '''
        获取windows平台的cpu信息

        Parameters
        ----------
        update : bool, optional
            强制更新数据. The default is False.

        Returns
        -------
        None
            DESCRIPTION.

        '''
        if update or not self.initialed:

            # 初始化wmi
            if self.WMI == None: self.InitWmi()

            # cpu列表
            self.cpuList: list = self.WMI.Win32_Processor()

            # 物理cpu个数
            self.cpuCount: int = len(self.cpuList)

            # cpu型号(名称)
            self.cpuName: str = self.cpuList[0].Name


            self.GetCpuConstantsBoth()


    @staticmethod
    def getCpuTypeUnix() -> str:
        '''
        获取CPU型号(unix)

        Returns
        -------
        str
            CPU型号.

        '''
        cpuinfo: str = readFile('/proc/cpuinfo')
        rep: str = 'model\s+name\s+:\s+(.+)'
        tmp = re.search(rep,cpuinfo,re.I)
        cpuType: str = ''
        if tmp:
            cpuType: str = tmp.groups()[0]
        else:
            cpuinfo = ExecShellUnix('LANG="en_US.UTF-8" && lscpu')[0]
            rep = 'Model\s+name:\s+(.+)'
            tmp = re.search(rep,cpuinfo,re.I)
            if tmp: cpuType = tmp.groups()[0]
        return cpuType


def GetCpuInfo(interval: int = 1, constants: bool = True) -> Dict[str, Any]:
    '''
    获取CPU信息

    Parameters
    ----------
    interval : int, optional
        DESCRIPTION. The default is 1.

    Returns
    -------
    Dict[float, list, dict]
        DESCRIPTION.

    '''
    time.sleep(0.5)


    # cpu总使用率
    used: float = psutil.cpu_percent(interval)

    # 每个逻辑cpu使用率
    usedList: List[float] = psutil.cpu_percent(percpu=True)


    return {
    
    'used': used, 'used_list': usedList, **(cpuConstants.getDict if constants else {
    
    })}


def readFile(filename: str) -> str:
    '''
    读取文件内容

    Parameters
    ----------
    filename : str
        文件名.

    Returns
    -------
    str
        文件内容.

    '''
    try:
        with open(filename, 'r', encoding='utf-8') as file: return file.read()
    except:
        pass

    return ''


def GetLoadAverage() -> dict:
    '''
    获取服务器负载状态(多平台)

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    try: c: list = os.getloadavg()
    except: c: list = [0,0,0]
    data: dict = {
    
    i: c[idx] for idx, i in enumerate(('one', 'five', 'fifteen'))}
    data['max'] = psutil.cpu_count() * 2
    data['limit'] = data['max']
    data['safe'] = data['max'] * 0.75
    return data


def GetMemInfo() -> dict:
    '''
    获取内存信息(多平台)

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    if UNIX: return GetMemInfoUnix()
    return GetMemInfoWindows()


def GetMemInfoUnix() -> Dict[str, int]:
    '''
    获取内存信息(unix)

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    mem = psutil.virtual_memory()
    memInfo: dict = {
    
    
        'memTotal': ToSizeInt(mem.total, 'MB'),
        'memFree': ToSizeInt(mem.free, 'MB'),
        'memBuffers': ToSizeInt(mem.buffers, 'MB'),
        'memCached': ToSizeInt(mem.cached, 'MB'),
    }
    memInfo['memRealUsed'] = \
        memInfo['memTotal'] - \
        memInfo['memFree'] - \
        memInfo['memBuffers'] - \
        memInfo['memCached']

    memInfo['memUsedPercent'] = memInfo['memRealUsed'] / memInfo['memTotal'] * 100

    return memInfo


def GetMemInfoWindows() -> dict:
    '''
    获取内存信息(windows)

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    mem = psutil.virtual_memory()
    memInfo: dict = {
    
    
        'memTotal': ToSizeInt(mem.total, 'MB'),
        'memFree': ToSizeInt(mem.free, 'MB'),
        'memRealUsed': ToSizeInt(mem.used, 'MB'),
        'menUsedPercent': mem.used / mem.total * 100
    }

    return memInfo


def ToSizeInt(byte: int, target: str) -> int:
    '''
    将字节大小转换为目标单位的大小

    Parameters
    ----------
    byte : int
        int格式的字节大小(bytes size)
    target : str
        目标单位,str.

    Returns
    -------
    int
        转换为目标单位后的字节大小.

    '''
    return int(byte/1024**(('KB','MB','GB','TB').index(target) + 1))


def ToSizeString(byte: int) -> str:
    '''
    获取字节大小字符串

    Parameters
    ----------
    byte : int
        int格式的字节大小(bytes size).

    Returns
    -------
    str
        自动转换后的大小字符串,如:6.90 GB.

    '''
    units: tuple = ('b','KB','MB','GB','TB')
    re = lambda: '{:.2f} {}'.format(byte, u)
    for u in units:
        if byte < 1024: return re()
        byte /= 1024
    return re()


def GetDiskInfo() -> list:
    '''
    获取磁盘信息(多平台)

    Returns
    -------
    list
        列表.

    '''
    try:
        if UNIX: return GetDiskInfoUnix()
        return GetDiskInfoWindows()
    except Exception as err:
        log('获取磁盘信息异常(unix: {}):'.format(UNIX), err)
        return []


def GetDiskInfoWindows() -> list:
    '''
    获取磁盘信息Windows

    Returns
    -------
    diskInfo : list
        列表.

    '''
    diskIo: list = psutil.disk_partitions()
    diskInfo: list = []
    for disk in diskIo:
        tmp: dict = {
    
    }
        try:
            tmp['path'] = disk.mountpoint.replace("\\","/")
            usage = psutil.disk_usage(disk.mountpoint)
            tmp['size'] = {
    
    
                'total': usage.total,
                'used': usage.used,
                'free': usage.free,
                'percent': usage.percent
            }
            tmp['fstype'] = disk.fstype
            tmp['inodes'] = False
            diskInfo.append(tmp)
        except:
            pass
    return diskInfo


def GetDiskInfoUnix() -> list:
     '''
    获取硬盘分区信息(unix)

    Returns
    -------
    list
        DESCRIPTION.

    '''
     temp: list = (
         ExecShellUnix("df -h -P|grep '/'|grep -v tmpfs")[0]).split('\n')
     tempInodes: list = (
         ExecShellUnix("df -i -P|grep '/'|grep -v tmpfs")[0]).split('\n')
     diskInfo: list = []
     n: int = 0
     cuts: list = [
         '/mnt/cdrom',
         '/boot',
         '/boot/efi',
         '/dev',
         '/dev/shm',
         '/run/lock',
         '/run',
         '/run/shm',
         '/run/user'
     ]
     for tmp in temp:
         n += 1
         try:
             inodes: list = tempInodes[n-1].split()
             disk: list = tmp.split()
             if len(disk) < 5: continue
             if disk[1].find('M') != -1: continue
             if disk[1].find('K') != -1: continue
             if len(disk[5].split('/')) > 10: continue
             if disk[5] in cuts: continue
             if disk[5].find('docker') != -1: continue
             arr = {
    
    }
             arr['path'] = disk[5]
             tmp1 = [disk[1],disk[2],disk[3],disk[4]]
             arr['size'] = tmp1
             arr['inodes'] = [inodes[1],inodes[2],inodes[3],inodes[4]]
             diskInfo.append(arr)
         except Exception as ex:
             log('信息获取错误:', str(ex))
             continue
     return diskInfo



def md5(strings: str) -> str:
    '''
    生成md5

    Parameters
    ----------
    strings : TYPE
        要进行hash处理的字符串

    Returns
    -------
    str[32]
        hash后的字符串.

    '''

    m = hashlib.md5()
    m.update(strings.encode('utf-8'))
    return m.hexdigest()


def GetErrorInfo() -> str:
    '''
    获取traceback中的错误

    Returns
    -------
    str
        DESCRIPTION.

    '''
    import traceback
    errorMsg = traceback.format_exc()
    return errorMsg


def ExecShellUnix(cmdstring: str, shell=True):
    '''
    执行Shell命令(Unix)

    Parameters
    ----------
    cmdstring : str
        DESCRIPTION.
    shell : TYPE, optional
        DESCRIPTION. The default is True.

    Returns
    -------
    a : TYPE
        DESCRIPTION.
    e : TYPE
        DESCRIPTION.

    '''
    a: str = ''
    e: str = ''
    import subprocess,tempfile

    try:
        rx: str = md5(cmdstring)
        succ_f = tempfile.SpooledTemporaryFile(
            max_size = 4096,
            mode = 'wb+',
            suffix = '_succ',
            prefix = 'btex_' + rx ,
            dir = '/dev/shm'
        )
        err_f = tempfile.SpooledTemporaryFile(
            max_size = 4096,
            mode = 'wb+',
            suffix = '_err',
            prefix = 'btex_' + rx ,
            dir = '/dev/shm'
        )
        sub = subprocess.Popen(
            cmdstring,
            close_fds = True,
            shell = shell,
            bufsize = 128,
            stdout = succ_f,
            stderr = err_f
        )
        sub.wait()
        err_f.seek(0)
        succ_f.seek(0)
        a = succ_f.read()
        e = err_f.read()
        if not err_f.closed: err_f.close()
        if not succ_f.closed: succ_f.close()
    except Exception as err:
        log(err)
    try:
        if type(a) == bytes: a = a.decode('utf-8')
        if type(e) == bytes: e = e.decode('utf-8')
    except Exception as err:
        log(err)

    return a,e


def GetNetWork() -> dict:
    '''
    获取系统网络信息

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    networkIo: list = [0,0,0,0]
    cache_timeout: int = 86400
    try:
        networkIo = psutil.net_io_counters()[:4]
    except:
        pass

    otime = cache.get("otime")
    if not otime:
        otime = time.time()
        cache.set('up',networkIo[0],cache_timeout)
        cache.set('down',networkIo[1],cache_timeout)
        cache.set('otime',otime ,cache_timeout)

    ntime = time.time()
    networkInfo: dict = {
    
    'up': 0, 'down': 0}
    networkInfo['upTotal']   = networkIo[0]
    networkInfo['downTotal'] = networkIo[1]
    try:
        networkInfo['up'] = round(
            float(networkIo[0] - cache.get("up")) / 1024 / (ntime - otime),
            2
        )
        networkInfo['down'] = round(
            float(networkIo[1] - cache.get("down")) / 1024 / (ntime -  otime),
            2
        )
    except:
        pass

    networkInfo['downPackets'] = networkIo[3]
    networkInfo['upPackets'] = networkIo[2]

    cache.set('up',networkIo[0],cache_timeout)
    cache.set('down',networkIo[1],cache_timeout)
    cache.set('otime', time.time(),cache_timeout)

    return networkInfo


def GetSystemInfo() -> dict:
    systemInfo: dict = {
    
    }
    systemInfo['cpu'] = GetCpuInfo()
    systemInfo['load'] = GetLoadAverage()
    systemInfo['mem'] = GetMemInfo()
    systemInfo['disk'] = GetDiskInfo()

    return systemInfo



def GetIoReadWrite() -> Dict[str, int]:
    '''
    获取系统IO读写

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    ioDisk = psutil.disk_io_counters()
    ioTotal: dict = {
    
    }
    ioTotal['write'] = GetIoWrite(ioDisk.write_bytes)
    ioTotal['read'] = GetIoRead(ioDisk.read_bytes)
    return ioTotal


def GetIoWrite(ioWrite: int) -> int:
    '''
    获取IO写

    Parameters
    ----------
    ioWrite : TYPE
        DESCRIPTION.

    Returns
    -------
    int
        DESCRIPTION.

    '''
    diskWrite: int = 0
    oldWrite: int = cache.get('io_write')
    if not oldWrite:
        cache.set('io_write', ioWrite)
        return diskWrite;

    oldTime: float = cache.get('io_time')
    newTime: float = time.time()
    if not oldTime: oldTime = newTime
    ioEnd: int = (ioWrite - oldWrite)
    timeEnd: float = (time.time() - oldTime)
    if ioEnd > 0:
        if timeEnd < 1: timeEnd = 1
        diskWrite = ioEnd / timeEnd
    cache.set('io_write',ioWrite)
    cache.set('io_time',newTime)
    if diskWrite > 0: return int(diskWrite)
    return 0


def GetIoRead(ioRead):
    '''
    读取IO读

    Parameters
    ----------
    ioRead : TYPE
        DESCRIPTION.

    Returns
    -------
    TYPE
        DESCRIPTION.

    '''
    diskRead: int = 0
    oldRead: int = cache.get('io_read')
    if not oldRead:
        cache.set('io_read',ioRead)
        return diskRead;
    oldTime: float = cache.get('io_time')
    newTime: float = time.time()
    if not oldTime: oldTime = newTime
    ioEnd: int = (ioRead - oldRead)
    timeEnd: float = (time.time() - oldTime)
    if ioEnd > 0:
        if timeEnd < 1: timeEnd = 1;
        diskRead = ioEnd / timeEnd;
    cache.set('io_read', ioRead)
    if diskRead > 0: return int(diskRead)
    return 0


def GetRegValue(key: str, subkey: str, value: str) -> Any:
    '''
    获取系统注册表信息

    Parameters
    ----------
    key : str
        类型.
    subkey : str
        路径.
    value : str
        key.

    Returns
    -------
    value : Any
        DESCRIPTION.

    '''
    import winreg
    key = getattr(winreg, key)
    handle = winreg.OpenKey(key, subkey)
    (value, type) = winreg.QueryValueEx(handle, value)
    return value


def GetSystemVersion() -> str:
    '''
    获取操作系统版本(多平台)

    Returns
    -------
    str
        DESCRIPTION.

    '''
    if UNIX: return GetSystemVersionUnix()
    return GetSystemVersionWindows()


def GetSystemVersionWindows() -> str:
    '''
    获取操作系统版本(windows)

    Returns
    -------
    str
        DESCRIPTION.

    '''
    try:
        import platform
        bit: str = 'x86';
        if 'PROGRAMFILES(X86)' in os.environ: bit = 'x64'

        def get(key: str):
            return GetRegValue(
                "HKEY_LOCAL_MACHINE",
                "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
                key
            )

        osName = get('ProductName')
        build = get('CurrentBuildNumber')

        version: str = '{} (build {}) {} (Py{})'.format(
            osName, build, bit, platform.python_version())
        return version
    except Exception as ex:
        log('获取系统版本失败,错误:' + str(ex))
        return '未知系统版本.'


def GetSystemVersionUnix() -> str:
    '''
    获取系统版本(unix)

    Returns
    -------
    str
        系统版本.

    '''
    try:
        version: str = readFile('/etc/redhat-release')
        if not version:
            version = readFile(
                '/etc/issue'
            ).strip().split("\n")[0].replace('\\n','').replace('\l','').strip()
        else:
            version = version.replace(
                'release ',''
            ).replace('Linux','').replace('(Core)','').strip()
        v = sys.version_info
        return version + '(Py {}.{}.{})'.format(v.major, v.minor, v.micro)
    except Exception as err:
        log('获取系统版本失败,错误:', err)
        return '未知系统版本.'


def GetBootTime() -> dict:
    '''
    获取当前系统启动时间

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    bootTime: float = psutil.boot_time()
    return {
    
    
        'timestamp': bootTime,
        'runtime': time.time() - bootTime,
        'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    }


def GetCpuConstants() -> dict:
    '''
    获取CPU常量信息

    Parameters
    ----------
    cpuConstants : CpuConstants
        DESCRIPTION.

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    return cpuConstants.getDict


def GetFullSystemData() -> dict:
    '''
    获取完全的系统信息

    Returns
    -------
    dict
        DESCRIPTION.

    '''
    systemData: dict = {
    
    
        **GetSystemInfo(),
        'network': {
    
     **GetNetWork() },
        'io': {
    
     **GetIoReadWrite() },
        'boot': {
    
     **GetBootTime() },
        'time': time.time()
    }
    return systemData

cpuConstants = CpuConstants()
log('systemInfo 模块初始化完毕!')

if __name__ == '__main__':
    log(GetFullSystemData())
    log(GetCpuConstants())
    log(GetSystemInfo())
    log(GetNetWork())
    log(GetIoReadWrite())

utils.py

工具函数

'''
@author: Pure-Peace
@name: 工具函数
@time: 2020年8月17日
@version: 0.1
'''
import datetime
import time

def log(text: str, *args) -> None:
    '''
    logger,打印日志用,与print用法一致,但会显示时间

    Parameters
    ----------
    text : str
        DESCRIPTION.
    *args : TYPE
        DESCRIPTION.

    Returns
    -------
    None
        DESCRIPTION.

    '''
    print('[{}] {}'.format(getTime(1), text), *args)


def getTime(needFormat: int = 0, formatMS: bool = True) -> [int, str]:
    '''
    获取当前时间

    Parameters
    ----------
    needFormat : int, optional
        需要格式化为2020年8月17日 20:01:40这样的字符串?. The default is 0.
    formatMS : bool, optional
        需要精确到毫秒吗?. The default is True.

    Returns
    -------
    [int, str]
        DESCRIPTION.

    '''
    if needFormat != 0:
        return datetime.datetime.now().strftime(f'%Y-%m-%d %H:%M:%S{r".%f" if formatMS else ""}')
    return int(str(time.time()).split('.')[0])

运行

虚拟环境

当前提供windows x64下已安装依赖的虚拟环境(python3.8):
https://github.com/Pure-Peace/system-info-api/blob/master/venv_windows.zip

在这里插入图片描述

将其解压到项目目录下,运行run.bat即可

非虚拟环境

请手动安装python3解释器,并使用命令安装依赖

pip install -r requirements.txt

然后运行

python main.py

运行后,访问地址

http://localhost:5678

即启动成功

{
"message": "hello",
"status": 1
}

[初次]运行后等待5-8秒,项目目录下将会出现缓存的json文件

例如

cpuInfo.json
memInfo.json
ioInfo.json
networkInfo.json
loadInfo.json

这些文件的内容将会不断更新。

您可以通过下列地址访问这些系统信息的缓存:

http://localhost:5678/cpu_constants
http://localhost:5678/cpu_info
http://localhost:5678/io_info
http://localhost:5678/mem_info
http://localhost:5678/network_info
http://localhost:5678/load_info

测试socketio

打开python服务端后,用浏览器打开socketio.html

在这里插入图片描述

在网页建立一个socketio对象,连接到服务端
socketio:https://socket.io/#examples

以下是socketio的更新事件(event):

update_cpu
update_io
update_mem
update_net
update_load

Pure-Peace

猜你喜欢

转载自blog.csdn.net/qq_26373925/article/details/108066722