mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-30 21:49:37 +03:00
Refactor exports modules loading
This commit is contained in:
parent
23292675a3
commit
a0b5982f1d
3
Makefile
3
Makefile
@ -62,6 +62,9 @@ run-client: venv
|
||||
run-browser: venv
|
||||
./venv/bin/python -m glances -C ./conf/glances.conf --browser
|
||||
|
||||
run-export-influxdb: venv
|
||||
./venv/bin/python -m glances -C ./conf/glances.conf --export influxdb
|
||||
|
||||
show-version: venv
|
||||
./venv/bin/python -m glances -C ./conf/glances.conf -V
|
||||
|
||||
|
@ -52,8 +52,8 @@ except locale.Error:
|
||||
print("Warning: Unable to set locale. Expect encoding problems.")
|
||||
|
||||
# Check Python version
|
||||
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.')
|
||||
if sys.version_info < (3, 4):
|
||||
print('Glances requires at least Python 3.4 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
# Check psutil version
|
||||
|
@ -24,7 +24,7 @@ from datetime import datetime
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
from glances.globals import iteritems
|
||||
|
||||
from cassandra.auth import PlainTextAuthProvider
|
@ -23,7 +23,7 @@ import sys
|
||||
from datetime import datetime
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
import couchdb
|
||||
import couchdb.mapping
|
@ -26,7 +26,7 @@ import time
|
||||
|
||||
from glances.globals import PY3, iterkeys, itervalues
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
@ -23,7 +23,7 @@ import sys
|
||||
from datetime import datetime
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from elasticsearch import Elasticsearch, helpers
|
||||
from elasticsearch import __version__ as elk_version
|
@ -23,7 +23,7 @@ import sys
|
||||
from platform import node
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from influxdb import InfluxDBClient
|
||||
from influxdb.client import InfluxDBClientError
|
@ -29,7 +29,7 @@ import errno
|
||||
from glances.logger import logger
|
||||
from glances.timer import Timer
|
||||
from glances.globals import iteritems, time_serie_subsample
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
@ -23,7 +23,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from graphitesend import GraphiteClient
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
from platform import node
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from influxdb_client import InfluxDBClient, WriteOptions
|
||||
|
@ -5,7 +5,7 @@ import json
|
||||
|
||||
from glances.globals import PY3, listkeys
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
@ -23,7 +23,7 @@ import sys
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.globals import iteritems
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from kafka import KafkaProducer
|
||||
import json
|
@ -24,7 +24,7 @@ import string
|
||||
import json
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
# Import paho for MQTT
|
||||
from requests import certs
|
||||
@ -118,14 +118,14 @@ class Export(GlancesExport):
|
||||
output_value = dict()
|
||||
for key in sensor_values:
|
||||
split_key = key.split('.')
|
||||
|
||||
|
||||
# Add the parent keys if they don't exist
|
||||
current_level = output_value
|
||||
for depth in range(len(split_key) - 1):
|
||||
if split_key[depth] not in current_level:
|
||||
current_level[split_key[depth]] = dict()
|
||||
current_level = current_level[split_key[depth]]
|
||||
|
||||
|
||||
# Add the value
|
||||
current_level[split_key[len(split_key) - 1]] = sensor_values[key]
|
||||
|
||||
@ -133,4 +133,4 @@ class Export(GlancesExport):
|
||||
self.client.publish(topic, json_value)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to MQTT server (%s)" % e)
|
||||
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
import potsdb
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
from glances.globals import iteritems, listkeys
|
||||
|
||||
from prometheus_client import start_http_server, Gauge
|
@ -25,7 +25,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
# Import pika for RabbitMQ
|
||||
import pika
|
@ -23,7 +23,7 @@ import sys
|
||||
|
||||
from glances.globals import listkeys
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from requests import post
|
||||
|
@ -24,7 +24,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
# Import bernhard for Riemann
|
||||
import bernhard
|
@ -23,7 +23,7 @@ import sys
|
||||
from numbers import Number
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
from statsd import StatsClient
|
||||
|
@ -24,7 +24,7 @@ import json
|
||||
|
||||
from glances.globals import b
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
from glances.exports.export import GlancesExport
|
||||
|
||||
import zmq
|
||||
from zmq.utils.strtypes import asbytes
|
@ -29,11 +29,6 @@ from glances.plugins.plugin import GlancesPlugin
|
||||
import psutil
|
||||
|
||||
# Fields description
|
||||
# description: human readable description
|
||||
# short_name: shortname to use un UI
|
||||
# unit: unit type
|
||||
# rate: is it a rate ? If yes, // by time_since_update when displayed,
|
||||
# min_symbol: Auto unit should be used if value > than 1 'X' (K, M, G)...
|
||||
fields_description = {
|
||||
'total': {'description': 'Sum of all CPU percentages (except idle).',
|
||||
'unit': 'percent'},
|
||||
@ -65,21 +60,12 @@ CPU while the hypervisor is servicing another virtual processor.',
|
||||
second. A context switch is a procedure that a computer\'s CPU (central \
|
||||
processing unit) follows to change from one task (or process) to \
|
||||
another while ensuring that the tasks do not conflict.',
|
||||
'unit': 'number',
|
||||
'rate': True,
|
||||
'min_symbol': 'K',
|
||||
'short_name': 'ctx_sw'},
|
||||
'unit': 'percent'},
|
||||
'interrupts': {'description': 'number of interrupts per second.',
|
||||
'unit': 'number',
|
||||
'rate': True,
|
||||
'min_symbol': 'K',
|
||||
'short_name': 'inter'},
|
||||
'unit': 'percent'},
|
||||
'soft_interrupts': {'description': 'number of software interrupts per second. Always set to \
|
||||
0 on Windows and SunOS.',
|
||||
'unit': 'number',
|
||||
'rate': True,
|
||||
'min_symbol': 'K',
|
||||
'short_name': 'sw_int'},
|
||||
'unit': 'percent'},
|
||||
'cpucore': {'description': 'Total number of CPU core.',
|
||||
'unit': 'number'},
|
||||
'time_since_update': {'description': 'Number of seconds since last update.',
|
||||
@ -281,12 +267,12 @@ class Plugin(GlancesPlugin):
|
||||
if not self.stats or self.args.percpu or self.is_disable():
|
||||
return ret
|
||||
|
||||
# Build the string message
|
||||
# If user stat is not here, display only idle / total CPU usage (for
|
||||
# exemple on Windows OS)
|
||||
idle_tag = 'user' not in self.stats
|
||||
|
||||
# First line
|
||||
# Total + (idle) + ctx_sw
|
||||
# Header
|
||||
msg = '{}'.format('CPU')
|
||||
ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
trend_user = self.get_trend('user')
|
||||
@ -302,47 +288,103 @@ class Plugin(GlancesPlugin):
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='total', option='decoration')))
|
||||
# Idle CPU
|
||||
if not idle_tag:
|
||||
ret.extend(self.curse_add_stat('idle', width=15, header=' '))
|
||||
if 'idle' in self.stats and not idle_tag:
|
||||
msg = ' {:8}'.format('idle:')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:5.1f}%'.format(self.stats['idle'])
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# ctx_switches
|
||||
ret.extend(self.curse_add_stat('ctx_switches', width=15, header=' '))
|
||||
if 'ctx_switches' in self.stats:
|
||||
msg = ' {:8}'.format('ctx_sw:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='ctx_switches', option='optional')))
|
||||
msg = '{:>5}'.format(self.auto_unit(int(self.stats['ctx_switches'] // self.stats['time_since_update']),
|
||||
min_symbol='K'))
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='ctx_switches', option='decoration'),
|
||||
optional=self.get_views(key='ctx_switches', option='optional')))
|
||||
|
||||
# Second line
|
||||
# user|idle + irq + interrupts
|
||||
# New line
|
||||
ret.append(self.curse_new_line())
|
||||
# User CPU
|
||||
if not idle_tag:
|
||||
ret.extend(self.curse_add_stat('user', width=15))
|
||||
if 'user' in self.stats:
|
||||
msg = '{:8}'.format('user:')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:5.1f}%'.format(self.stats['user'])
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='user', option='decoration')))
|
||||
elif 'idle' in self.stats:
|
||||
ret.extend(self.curse_add_stat('idle', width=15))
|
||||
msg = '{:8}'.format('idle:')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:5.1f}%'.format(self.stats['idle'])
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# IRQ CPU
|
||||
ret.extend(self.curse_add_stat('irq', width=15, header=' '))
|
||||
if 'irq' in self.stats:
|
||||
msg = ' {:8}'.format('irq:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='irq', option='optional')))
|
||||
msg = '{:5.1f}%'.format(self.stats['irq'])
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='irq', option='optional')))
|
||||
# interrupts
|
||||
ret.extend(self.curse_add_stat('interrupts', width=15, header=' '))
|
||||
if 'interrupts' in self.stats:
|
||||
msg = ' {:8}'.format('inter:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='interrupts', option='optional')))
|
||||
msg = '{:>5}'.format(int(self.stats['interrupts'] // self.stats['time_since_update']))
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='interrupts', option='optional')))
|
||||
|
||||
# Third line
|
||||
# system|core + nice + sw_int
|
||||
# New line
|
||||
ret.append(self.curse_new_line())
|
||||
# System CPU
|
||||
if not idle_tag:
|
||||
ret.extend(self.curse_add_stat('system', width=15))
|
||||
if 'system' in self.stats and not idle_tag:
|
||||
msg = '{:8}'.format('system:')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:5.1f}%'.format(self.stats['system'])
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='system', option='decoration')))
|
||||
else:
|
||||
ret.extend(self.curse_add_stat('core', width=15))
|
||||
msg = '{:8}'.format('core:')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>6}'.format(self.stats['nb_log_core'])
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# Nice CPU
|
||||
ret.extend(self.curse_add_stat('nice', width=15, header=' '))
|
||||
if 'nice' in self.stats:
|
||||
msg = ' {:8}'.format('nice:')
|
||||
ret.append(self.curse_add_line(
|
||||
msg, optional=self.get_views(key='nice', option='optional')))
|
||||
msg = '{:5.1f}%'.format(self.stats['nice'])
|
||||
ret.append(self.curse_add_line(
|
||||
msg, optional=self.get_views(key='nice', option='optional')))
|
||||
# soft_interrupts
|
||||
ret.extend(self.curse_add_stat('soft_interrupts', width=15, header=' '))
|
||||
if 'soft_interrupts' in self.stats:
|
||||
msg = ' {:8}'.format('sw_int:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional')))
|
||||
msg = '{:>5}'.format(int(self.stats['soft_interrupts'] // self.stats['time_since_update']))
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional')))
|
||||
|
||||
# Fourth line
|
||||
# iowat + steal + syscalls
|
||||
# New line
|
||||
ret.append(self.curse_new_line())
|
||||
# IOWait CPU
|
||||
ret.extend(self.curse_add_stat('iowait', width=15))
|
||||
if 'iowait' in self.stats:
|
||||
msg = '{:8}'.format('iowait:')
|
||||
ret.append(self.curse_add_line(
|
||||
msg, optional=self.get_views(key='iowait', option='optional')))
|
||||
msg = '{:5.1f}%'.format(self.stats['iowait'])
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='iowait', option='decoration'),
|
||||
optional=self.get_views(key='iowait', option='optional')))
|
||||
# Steal CPU usage
|
||||
ret.extend(self.curse_add_stat('steal', width=15, header=' '))
|
||||
if 'steal' in self.stats:
|
||||
msg = ' {:8}'.format('steal:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='steal', option='optional')))
|
||||
msg = '{:5.1f}%'.format(self.stats['steal'])
|
||||
ret.append(self.curse_add_line(
|
||||
msg, self.get_views(key='steal', option='decoration'),
|
||||
optional=self.get_views(key='steal', option='optional')))
|
||||
# syscalls
|
||||
# syscalls: number of system calls since boot. Always set to 0 on Linux. (do not display)
|
||||
if not LINUX:
|
||||
ret.extend(self.curse_add_stat('syscalls', width=15, header=' '))
|
||||
if 'syscalls' in self.stats and not LINUX:
|
||||
msg = ' {:8}'.format('syscal:')
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='syscalls', option='optional')))
|
||||
msg = '{:>5}'.format(int(self.stats['syscalls'] // self.stats['time_since_update']))
|
||||
ret.append(self.curse_add_line(msg, optional=self.get_views(key='syscalls', option='optional')))
|
||||
|
||||
# Return the message with decoration
|
||||
return ret
|
||||
|
108
glances/stats.py
108
glances/stats.py
@ -103,39 +103,7 @@ class GlancesStats(object):
|
||||
# Restoring system path
|
||||
sys.path = sys_path
|
||||
|
||||
# TODO: To be removed and replace by the _load_plugin_v4
|
||||
def _load_plugin(self, plugin_script, args=None, config=None):
|
||||
"""Load the plugin (script), init it and add to the _plugin dict."""
|
||||
# The key is the plugin name
|
||||
# for example, the file glances_xxx.py
|
||||
# generate self._plugins_list["xxx"] = ...
|
||||
name = plugin_script[len(self.header):-3].lower()
|
||||
|
||||
# Loaf the plugin class
|
||||
try:
|
||||
# Import the plugin
|
||||
plugin = import_module(plugin_script[:-3])
|
||||
# Init and add the plugin to the dictionary
|
||||
self._plugins[name] = plugin.Plugin(args=args, config=config)
|
||||
except Exception as e:
|
||||
# If a plugin can not be loaded, display a critical message
|
||||
# on the console but do not crash
|
||||
logger.critical("Error while initializing the {} plugin ({})".format(name, e))
|
||||
logger.error(traceback.format_exc())
|
||||
# Disable the plugin
|
||||
if args is not None:
|
||||
setattr(args,
|
||||
'disable_' + name,
|
||||
False)
|
||||
else:
|
||||
# Set the disable_<name> to False by default
|
||||
if args is not None:
|
||||
setattr(args,
|
||||
'disable_' + name,
|
||||
getattr(args, 'disable_' + name, False))
|
||||
|
||||
# TODO: To be rename to _load_plugin
|
||||
def _load_plugin_v4(self, plugin_path, args=None, config=None):
|
||||
def _load_plugin(self, plugin_path, args=None, config=None):
|
||||
"""Load the plugin, init it and add to the _plugin dict."""
|
||||
# The key is the plugin name = plugin_path
|
||||
# for example, the path ./glances/plugins/xxx
|
||||
@ -173,24 +141,14 @@ class GlancesStats(object):
|
||||
def load_plugins(self, args=None):
|
||||
"""Load all plugins in the 'plugins' folder."""
|
||||
start_duration = Counter()
|
||||
|
||||
for item in os.listdir(plugins_path):
|
||||
if (item.startswith(self.header) and
|
||||
item.endswith(".py") and
|
||||
item != (self.header + "plugin.py")):
|
||||
if os.path.isdir(os.path.join(plugins_path, item)) and \
|
||||
not item.startswith('__'):
|
||||
# Load the plugin
|
||||
start_duration.reset()
|
||||
self._load_plugin(os.path.basename(item),
|
||||
args=args, config=self.config)
|
||||
logger.debug("Plugin {} started in {} seconds".format(item,
|
||||
start_duration.get()))
|
||||
for item in os.listdir(plugins_path):
|
||||
if os.path.isdir(os.path.join(plugins_path, item)) and \
|
||||
not item.startswith('__') and \
|
||||
item != "plugin":
|
||||
# Load the plugin
|
||||
start_duration.reset()
|
||||
self._load_plugin_v4(os.path.basename(item),
|
||||
args=args, config=self.config)
|
||||
logger.debug("Plugin {} started in {} seconds".format(item,
|
||||
start_duration.get()))
|
||||
|
||||
@ -198,36 +156,40 @@ class GlancesStats(object):
|
||||
logger.debug("Active plugins list: {}".format(self.getPluginsList()))
|
||||
|
||||
def load_exports(self, args=None):
|
||||
"""Load all export modules in the 'exports' folder."""
|
||||
if args is None:
|
||||
return False
|
||||
header = "glances_"
|
||||
# Build the export module available list
|
||||
args_var = vars(locals()['args'])
|
||||
"""Load all exporters in the 'exports' folder."""
|
||||
start_duration = Counter()
|
||||
|
||||
if args is None: return False
|
||||
|
||||
for item in os.listdir(exports_path):
|
||||
export_name = os.path.basename(item)[len(header):-3].lower()
|
||||
if (item.startswith(header) and
|
||||
item.endswith(".py") and
|
||||
item != (header + "export.py") and
|
||||
item != (header + "history.py")):
|
||||
self._exports_all[export_name] = os.path.basename(item)[:-3]
|
||||
if os.path.isdir(os.path.join(exports_path, item)) and \
|
||||
not item.startswith('__'):
|
||||
# Load the exporter
|
||||
start_duration.reset()
|
||||
if item.startswith('glances_'):
|
||||
# Avoid circular loop when Glances exporter uses lib with same name
|
||||
# Example: influxdb should be named to glances_influxdb
|
||||
exporter_name = os.path.basename(item).split('glances_')[1]
|
||||
else:
|
||||
exporter_name = os.path.basename(item)
|
||||
# Set the disable_<name> to False by default
|
||||
setattr(self.args,
|
||||
'export_' + export_name,
|
||||
getattr(self.args, 'export_' + export_name, False))
|
||||
|
||||
# Aim is to check if the export module should be loaded
|
||||
for export_name in self._exports_all:
|
||||
if getattr(self.args, 'export_' + export_name, False):
|
||||
# Import the export module
|
||||
export_module = __import__(self._exports_all[export_name])
|
||||
# Add the export to the dictionary
|
||||
# The key is the module name
|
||||
# for example, the file glances_xxx.py
|
||||
# generate self._exports_list["xxx"] = ...
|
||||
self._exports[export_name] = export_module.Export(args=args,
|
||||
config=self.config)
|
||||
self._exports_all[export_name] = self._exports[export_name]
|
||||
'export_' + exporter_name,
|
||||
getattr(self.args, 'export_' + exporter_name, False))
|
||||
# We should import the module
|
||||
if getattr(self.args, 'export_' + exporter_name, False):
|
||||
# Import the export module
|
||||
export_module = import_module(item)
|
||||
# Add the exporter instance to the active exporters dictionary
|
||||
self._exports[exporter_name] = export_module.Export(args=args,
|
||||
config=self.config)
|
||||
# Add the exporter instance to the available exporters dictionary
|
||||
self._exports_all[exporter_name] = self._exports[exporter_name]
|
||||
else:
|
||||
# Add the exporter name to the available exporters dictionary
|
||||
self._exports_all[exporter_name] = exporter_name
|
||||
logger.debug("Exporter {} started in {} seconds".format(exporter_name,
|
||||
start_duration.get()))
|
||||
|
||||
# Log plugins list
|
||||
logger.debug("Active exports modules list: {}".format(self.getExportsList()))
|
||||
|
@ -26,6 +26,12 @@ import subprocess
|
||||
import time
|
||||
import numbers
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
# Check Python version
|
||||
if sys.version_info < (3, 4):
|
||||
print('Glances requires at least Python 3.4 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
from glances import __version__
|
||||
from glances.globals import text_type
|
||||
|
@ -26,6 +26,12 @@ import shlex
|
||||
import subprocess
|
||||
import time
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
# Check Python version
|
||||
if sys.version_info < (3, 4):
|
||||
print('Glances requires at least Python 3.4 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
from glances import __version__
|
||||
from glances.globals import ServerProxy
|
||||
|
@ -22,6 +22,12 @@
|
||||
|
||||
import time
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
# Check Python version
|
||||
if sys.version_info < (3, 4):
|
||||
print('Glances requires at least Python 3.4 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
from glances.main import GlancesMain
|
||||
from glances.stats import GlancesStats
|
||||
|
Loading…
Reference in New Issue
Block a user