From 83d47a8bc9c0de6eebdd81585ababc6b283c8e0e Mon Sep 17 00:00:00 2001 From: Alessio Sergi Date: Thu, 15 Feb 2018 18:15:18 +0100 Subject: [PATCH] Drop support for psutil < 5.3.0 Issue #1055 has been fixed in psutil 5.3.0 (see giampaolo/psutil#1074). --- NEWS | 1 + README.rst | 2 +- glances/__init__.py | 6 ++-- glances/globals.py | 4 +-- glances/plugins/glances_batpercent.py | 10 +++--- glances/plugins/glances_cpu.py | 49 ++++++++++++-------------- glances/plugins/glances_network.py | 18 ++++------ glances/plugins/glances_processlist.py | 3 +- glances/plugins/glances_sensors.py | 15 +++----- glances/processes.py | 38 ++++++-------------- setup.py | 2 +- 11 files changed, 57 insertions(+), 91 deletions(-) diff --git a/NEWS b/NEWS index 2a49d29e..6373c99e 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,7 @@ Bugs corrected: Backward-incompatible changes: * Support for Python 3.3 has been dropped (EOL 2017-09-29) + * Support for psutil < 5.3.0 has been dropped * Minimum supported Docker API version is now 1.21 (Docker plugins) * Support for InfluxDB < 0.9 is deprecated (InfluxDB exporter) * Remove graph export from Glances diff --git a/README.rst b/README.rst index e7cfd20f..37a7a7df 100644 --- a/README.rst +++ b/README.rst @@ -52,7 +52,7 @@ Requirements ============ - ``python 2.7,>=3.4`` -- ``psutil>=2.0.0`` (better with latest version) +- ``psutil>=5.3.0`` (better with latest version) Optional dependencies: diff --git a/glances/__init__.py b/glances/__init__.py index 7248b9a8..5861eb4e 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -55,11 +55,11 @@ if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 4): print('Glances requires at least Python 2.7 or 3.4 to run.') sys.exit(1) -# Check PSutil version -psutil_min_version = (2, 0, 0) +# Check psutil version +psutil_min_version = (5, 3, 0) psutil_version_info = tuple([int(num) for num in psutil_version.split('.')]) if psutil_version_info < psutil_min_version: - print('PSutil 2.0 or higher is needed. Glances cannot start.') + print('psutil 5.3.0 or higher is needed. Glances cannot start.') sys.exit(1) diff --git a/glances/globals.py b/glances/globals.py index 4edbdf6f..9d63290b 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -23,9 +23,7 @@ import errno import os import sys -# Operating system flag -# Note: Somes libs depends of OS -# Note2: Included in PsUtil 4.0 or higher +# OS constants (some libraries/features are OS-dependent) BSD = sys.platform.find('bsd') != -1 LINUX = sys.platform.startswith('linux') MACOS = sys.platform.startswith('darwin') diff --git a/glances/plugins/glances_batpercent.py b/glances/plugins/glances_batpercent.py index 161958be..c8aa5944 100644 --- a/glances/plugins/glances_batpercent.py +++ b/glances/plugins/glances_batpercent.py @@ -29,15 +29,17 @@ batinfo_tag = True try: import batinfo except ImportError: - logger.debug("batpercent plugin - Batinfo library not found. Trying fallback to PsUtil.") + logger.debug("batinfo library not found. Fallback to psutil.") batinfo_tag = False -# PsUtil library 5.2.0 or higher (optional; Linux-only) +# Availability: +# Linux, Windows, FreeBSD (psutil>=5.1.0) +# macOS (psutil>=5.4.2) psutil_tag = True try: psutil.sensors_battery() except AttributeError: - logger.debug("batpercent plugin - PsUtil 5.2.0 or higher is needed to grab battery stats.") + logger.debug("Cannot grab battery status. Platform not supported.") psutil_tag = False @@ -110,7 +112,7 @@ class GlancesGrabBat(object): 'value': self.battery_percent, 'unit': '%'}] elif psutil_tag and hasattr(self.bat.sensors_battery(), 'percent'): - # Use the PSUtil 5.2.0 or higher lib to grab the stats + # Use psutil to grab the stats # Give directly the battery percent self.bat_list = [{ 'label': 'Battery', diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index f06e6fa8..89840e41 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -109,38 +109,33 @@ class Plugin(GlancesPlugin): if hasattr(cpu_times_percent, stat): self.stats[stat] = getattr(cpu_times_percent, stat) - # Additionnal CPU stats (number of events / not as a %) + # Additional CPU stats (number of events not as a %; psutil>=4.1.0) # ctx_switches: number of context switches (voluntary + involuntary) per second # interrupts: number of interrupts per second # soft_interrupts: number of software interrupts per second. Always set to 0 on Windows and SunOS. # syscalls: number of system calls since boot. Always set to 0 on Linux. - try: - cpu_stats = psutil.cpu_stats() - except AttributeError: - # cpu_stats only available with PSUtil 4.1 or + - pass + cpu_stats = psutil.cpu_stats() + # By storing time data we enable Rx/s and Tx/s calculations in the + # XML/RPC API, which would otherwise be overly difficult work + # for users of the API + time_since_update = getTimeSinceLastUpdate('cpu') + + # Previous CPU stats are stored in the cpu_stats_old variable + if not hasattr(self, 'cpu_stats_old'): + # First call, we init the cpu_stats_old var + self.cpu_stats_old = cpu_stats else: - # By storing time data we enable Rx/s and Tx/s calculations in the - # XML/RPC API, which would otherwise be overly difficult work - # for users of the API - time_since_update = getTimeSinceLastUpdate('cpu') - - # Previous CPU stats are stored in the cpu_stats_old variable - if not hasattr(self, 'cpu_stats_old'): - # First call, we init the cpu_stats_old var - self.cpu_stats_old = cpu_stats - else: - for stat in cpu_stats._fields: - if getattr(cpu_stats, stat) is not None: - self.stats[stat] = getattr(cpu_stats, stat) - getattr(self.cpu_stats_old, stat) - - self.stats['time_since_update'] = time_since_update - - # Core number is needed to compute the CTX switch limit - self.stats['cpucore'] = self.nb_log_core - - # Save stats to compute next step - self.cpu_stats_old = cpu_stats + for stat in cpu_stats._fields: + if getattr(cpu_stats, stat) is not None: + self.stats[stat] = getattr(cpu_stats, stat) - getattr(self.cpu_stats_old, stat) + + self.stats['time_since_update'] = time_since_update + + # Core number is needed to compute the CTX switch limit + self.stats['cpucore'] = self.nb_log_core + + # Save stats to compute next step + self.cpu_stats_old = cpu_stats def update_snmp(self): """Update CPU stats using SNMP.""" diff --git a/glances/plugins/glances_network.py b/glances/plugins/glances_network.py index 64c116ee..77621d76 100644 --- a/glances/plugins/glances_network.py +++ b/glances/plugins/glances_network.py @@ -87,13 +87,14 @@ class Plugin(GlancesPlugin): except UnicodeDecodeError: return self.stats - # New in PsUtil 3.0 + # New in psutil 3.0.0 # - import the interface's status (issue #765) # - import the interface's speed (issue #718) netstatus = {} try: netstatus = psutil.net_if_stats() - except (AttributeError, OSError): + except OSError: + # see psutil #797/glances #1106 pass # Previous network interface stats are stored in the network_old variable @@ -134,18 +135,11 @@ class Plugin(GlancesPlugin): except KeyError: continue else: - # Optional stats (only compliant with PsUtil 3.0+) # Interface status - try: - netstat['is_up'] = netstatus[net].isup - except (KeyError, AttributeError): - pass + netstat['is_up'] = netstatus[net].isup # Interface speed in Mbps, convert it to bps - # Can be always 0 on some OS - try: - netstat['speed'] = netstatus[net].speed * 1048576 - except (KeyError, AttributeError): - pass + # Can be always 0 on some OSes + netstat['speed'] = netstatus[net].speed * 1048576 # Finaly, set the key netstat['key'] = self.get_key() diff --git a/glances/plugins/glances_processlist.py b/glances/plugins/glances_processlist.py index 6acb3f39..df644fc7 100644 --- a/glances/plugins/glances_processlist.py +++ b/glances/plugins/glances_processlist.py @@ -262,8 +262,7 @@ class Plugin(GlancesPlugin): # the bare process name instead cmdline = p['cmdline'] try: - # XXX: remove `cmdline != ['']` when we'll drop support for psutil<4.0.0 - if cmdline and cmdline != ['']: + if cmdline: path, cmd, arguments = split_cmdline(cmdline) if os.path.isdir(path) and not args.process_short_name: msg = ' {}'.format(path) + os.sep diff --git a/glances/plugins/glances_sensors.py b/glances/plugins/glances_sensors.py index b4706717..62d95d22 100644 --- a/glances/plugins/glances_sensors.py +++ b/glances/plugins/glances_sensors.py @@ -226,14 +226,10 @@ class GlancesGrabSensors(object): self.init_temp = False self.stemps = {} try: - # psutil>=5.1.0 is required + # psutil>=5.1.0, Linux-only self.stemps = psutil.sensors_temperatures() except AttributeError: - logger.warning("Temperature sensors are only available on Linux") - logger.warning("PsUtil 5.1.0 or higher is needed to grab temperatures sensors") - except OSError as e: - # FreeBSD: If oid 'hw.acpi.battery' not present, Glances wont start #1055 - logger.error("Can not grab temperatures sensors ({})".format(e)) + logger.debug("Cannot grab temperatures. Platform not supported.") else: self.init_temp = True @@ -241,13 +237,10 @@ class GlancesGrabSensors(object): self.init_fan = False self.sfans = {} try: - # psutil>=5.2.0 is required + # psutil>=5.2.0, Linux-only self.sfans = psutil.sensors_fans() except AttributeError: - logger.warning("Fan speed sensors are only available on Linux") - logger.warning("PsUtil 5.2.0 or higher is needed to grab fans sensors") - except OSError as e: - logger.error("Can not grab fans sensors ({})".format(e)) + logger.debug("Cannot grab fans speed. Platform not supported.") else: self.init_fan = True diff --git a/glances/processes.py b/glances/processes.py index 002f23f7..a9f7d7bd 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -242,31 +242,16 @@ class GlancesProcesses(object): if not WINDOWS: standard_attrs += ['gids'] - # and build the processes stats list - try: - # PsUtil 2.0 or higher - self.processlist = [p.info for p in psutil.process_iter(attrs=standard_attrs, - ad_value=None) - # OS specifics processes filter - if not (BSD and p.info['name'] == 'idle') and - not (WINDOWS and p.info['name'] == 'System Idle Process') and - not (MACOS and p.info['name'] == 'kernel_task') and - # Kernel threads filter - not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0) and - # User filter - not (self._filter.is_filtered(p.info))] - except TypeError: - # Fallback for PsUtil 2.0 - before_filter = [p.as_dict(attrs=standard_attrs, ad_value=None) for p in psutil.process_iter()] - self.processlist = [p for p in before_filter - # OS specifics processes filter - if not (BSD and p['name'] == 'idle') and - not (WINDOWS and p['name'] == 'System Idle Process') and - not (MACOS and p['name'] == 'kernel_task') and - # Kernel threads filter - not (self.no_kernel_threads and LINUX and p['gids'].real == 0) and - # User filter - not (self._filter.is_filtered(p))] + # and build the processes stats list (psutil>=5.3.0) + self.processlist = [p.info for p in psutil.process_iter(attrs=standard_attrs, ad_value=None) + # OS-related processes filter + if not (BSD and p.info['name'] == 'idle') and + not (WINDOWS and p.info['name'] == 'System Idle Process') and + not (MACOS and p.info['name'] == 'kernel_task') and + # Kernel threads filter + not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0) and + # User filter + not (self._filter.is_filtered(p.info))] # Sort the processes list by the current sort_key self.processlist = sort_stats(self.processlist, @@ -305,11 +290,10 @@ class GlancesProcesses(object): extended['memory_swap'] = sum([v.swap for v in top_process.memory_maps()]) except psutil.NoSuchProcess: pass - except (psutil.AccessDenied, TypeError, NotImplementedError): + except (psutil.AccessDenied, NotImplementedError): # NotImplementedError: /proc/${PID}/smaps file doesn't exist # on kernel < 2.6.14 or CONFIG_MMU kernel configuration option # is not enabled (see psutil #533/glances #413). - # XXX: Remove TypeError once we'll drop psutil < 3.0.0. extended['memory_swap'] = None try: extended['tcp'] = len(top_process.connections(kind="tcp")) diff --git a/setup.py b/setup.py index b5d11b6d..94d7fec3 100755 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ def get_data_files(): def get_install_requires(): - requires = ['psutil>=2.0.0'] + requires = ['psutil>=5.3.0'] if sys.platform.startswith('win'): requires.append('bottle') -- GitLab