import platform import os import subprocess import re from collections import Callable from datetime import datetime, timedelta import psutil from pyspectator.monitoring import AbcMonitor from pyspectator.collection import LimitedTimeTable from pyspectator.temperature_reader import LinuxCpuTemperatureReader from pyspectator.temperature_reader import WindowsCpuTemperatureReader class Cpu(AbcMonitor): """Monitoring system of the Central Processing Unit. :param monitoring_latency: time interval (in seconds) between calls of the CPU scanner. :type monitoring_latency: int, float :param stats_interval: time interval (in seconds) between calls of the statistics collector. :type stats_interval: int, float Usage example: .. code-block:: python >>> from pyspectator.processor import Cpu >>> from time import sleep >>> cpu = Cpu(monitoring_latency=1) >>> cpu.name 'Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz' >>> cpu.count 2 >>> with cpu: ... for _ in range(8): ... cpu.load, cpu.temperature ... sleep(1.1) ... (22.6, 55) (6.1, 55) (5.5, 54) (7.1, 54) (5.6, 54) (7.0, 54) (10.2, 54) (6.6, 54) """ def __init__(self, monitoring_latency, stats_interval=None): super().__init__(monitoring_latency) self.__name = Cpu.__get_processor_name() self.__count = psutil.cpu_count() self.__load = None self.__temperature = None # Init temperature reader self.__temperature_reader = Cpu.__get_processor_temperature_reader() # Prepare to collect statistics if stats_interval is None: stats_interval = timedelta(hours=1) self.__load_stats = LimitedTimeTable(stats_interval) self.__temperature_stats = LimitedTimeTable(stats_interval) # Read updating value at first time self._monitoring_action() @property def name(self): """Full name of the CPU. :getter: Return full name of the CPU. Return ``None`` if undetermined. :setter: Not available. :type: string, None """ return self.__name @property def count(self): """Amount of a CPU cores. :getter: Return the number of logical CPUs in the system. Return ``None`` if undetermined. :setter: Not available. :type: int, None """ return self.__count @property def load(self): """CPU load in percent. :getter: Return CPU load in percent. From 0.00 to 100.00 or ``None`` if undetermined. :setter: Not available. :type: float, None """ return self.__load @property def temperature(self): """Temperature (in Celsius) of the CPU. :getter: Return temperature (in Celsius) of the CPU. Return ``None`` if undetermined. :setter: Not available. :type: int, None """ return self.__temperature @property def load_stats(self): """Statistics about CPU load. :getter: Return statistics about CPU load. :setter: Not available. :type: pyspectator.collection.LimitedTimeTable """ return self.__load_stats @property def temperature_stats(self): """Statistics about CPU temperature. :getter: Return statistics about CPU temperature. :setter: Not available. :type: pyspectator.collection.LimitedTimeTable """ return self.__temperature_stats def _monitoring_action(self): now = datetime.now() self.__load = psutil.cpu_percent() self.__load_stats[now] = self.__load if isinstance(self.__temperature_reader, Callable): try: self.__temperature = self.__temperature_reader() self.__temperature_stats[now] = self.__temperature except: print('Can\'t read CPU temperature') @classmethod def __get_processor_name(cls): cpu_name = None os_name = platform.system() if os_name == 'Windows': cpu_name = platform.processor() elif os_name == 'Darwin': os.environ['PATH'] = os.environ['PATH'] + os.pathsep + '/usr/sbin' command = ('sysctl', '-n', 'machdep.cpu.brand_string') output = subprocess.check_output(command) if output: cpu_name = output.decode().strip() elif os_name == 'Linux': all_info = subprocess.check_output('cat /proc/cpuinfo', shell=True) all_info = all_info.strip().split(os.linesep.encode()) for line in all_info: line = line.decode() if 'model name' not in line: continue cpu_name = re.sub('.*model name.*:', str(), line, 1).strip() break return cpu_name @classmethod def __get_processor_temperature_reader(cls): reader = None os_name = platform.system() if os_name == 'Windows': reader = WindowsCpuTemperatureReader.get_reader() elif os_name == 'Darwin': # TODO: try to use C lib - https://github.com/lavoiesl/osx-cpu-temp pass elif os_name == 'Linux': reader = LinuxCpuTemperatureReader.get_reader() return reader __all__ = ['Cpu']