Issues (46)

glances/__init__.py (2 issues)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# SPDX-FileCopyrightText: 2023 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
#
10
11
"""Init the Glances software."""
12
13
# Import system libs
14
import locale
15
import platform
16
import signal
17
import sys
18
19
# Global name
20
# Version should start and end with a numerical char
21
# See https://packaging.python.org/specifications/core-metadata/#version
22
__version__ = '3.4.0.5'
23
__author__ = 'Nicolas Hennion <[email protected]>'
24
__license__ = 'LGPLv3'
25
26
# Import psutil
27
try:
28
    from psutil import __version__ as psutil_version
29
except ImportError:
30
    print('psutil library not found. Glances cannot start.')
31
    sys.exit(1)
32
33
# Import Glances libs
34
# Note: others Glances libs will be imported optionally
35
from glances.compat import PY3
36
from glances.logger import logger
37
from glances.main import GlancesMain
38
from glances.timer import Counter
39
40
# Check locale
41
try:
42
    locale.setlocale(locale.LC_ALL, '')
43
except locale.Error:
44
    print("Warning: Unable to set locale. Expect encoding problems.")
45
46
# Check Python version
47
if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 4):
48
    print('Glances requires at least Python 2.7 or 3.4 to run.')
49
    sys.exit(1)
50
51
# Check psutil version
52
psutil_min_version = (5, 3, 0)
53
psutil_version_info = tuple([int(num) for num in psutil_version.split('.')])
54
if psutil_version_info < psutil_min_version:
55
    print('psutil 5.3.0 or higher is needed. Glances cannot start.')
56
    sys.exit(1)
57
58
# Trac malloc is only available on Python 3.4 or higher
59
if PY3:
60
    import tracemalloc
61
62
63
def __signal_handler(signal, frame):
64
    logger.debug("Signal {} catched".format(signal))
65
    end()
66
67
68
def end():
69
    """Stop Glances."""
70
    try:
71
        mode.end()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable mode does not seem to be defined.
Loading history...
72
    except (NameError, KeyError):
73
        # NameError: name 'mode' is not defined in case of interrupt shortly...
74
        # ...after starting the server mode (issue #1175)
75
        pass
76
77
    logger.info("Glances stopped gracefully")
78
79
    # The end...
80
    sys.exit(0)
81
82
83
def start(config, args):
84
    """Start Glances."""
85
86
    # Load mode
87
    global mode
88
89
    if args.trace_malloc or args.memory_leak:
90
        tracemalloc.start()
91
92
    start_duration = Counter()
93
94
    if core.is_standalone():
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable core does not seem to be defined.
Loading history...
95
        from glances.standalone import GlancesStandalone as GlancesMode
96
    elif core.is_client():
97
        if core.is_client_browser():
98
            from glances.client_browser import GlancesClientBrowser as GlancesMode
99
        else:
100
            from glances.client import GlancesClient as GlancesMode
101
    elif core.is_server():
102
        from glances.server import GlancesServer as GlancesMode
103
    elif core.is_webserver():
104
        from glances.webserver import GlancesWebServer as GlancesMode
105
106
    # Init the mode
107
    logger.info("Start {} mode".format(GlancesMode.__name__))
108
    mode = GlancesMode(config=config, args=args)
109
110
    # Start the main loop
111
    logger.debug("Glances started in {} seconds".format(start_duration.get()))
112
    if args.stop_after:
113
        logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time * args.memory_leak * 2))
114
115
    if args.memory_leak:
116
        print(
117
            'Memory leak detection, please wait ~{} seconds...'.format(
118
                args.stop_after * args.time * args.memory_leak * 2
119
            )
120
        )
121
        # First run without dump to fill the memory
122
        mode.serve_n(args.stop_after)
123
        # Then start the memory-leak loop
124
        snapshot_begin = tracemalloc.take_snapshot()
125
126
    if args.stdout_issue or args.stdout_apidoc:
127
        # Serve once for issue/test mode
128
        mode.serve_issue()
129
    else:
130
        # Serve forever
131
        mode.serve_forever()
132
133
    if args.memory_leak:
134
        snapshot_end = tracemalloc.take_snapshot()
135
        snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename')
136
        memory_leak = sum([s.size_diff for s in snapshot_diff])
137
        print("Memory consumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000))
138
        logger.info("Memory consumption (top 5):")
139
        for stat in snapshot_diff[:5]:
140
            logger.info(stat)
141
    elif args.trace_malloc:
142
        # See more options here: https://docs.python.org/3/library/tracemalloc.html
143
        snapshot = tracemalloc.take_snapshot()
144
        top_stats = snapshot.statistics("filename")
145
        print("[ Trace malloc - Top 10 ]")
146
        for stat in top_stats[:10]:
147
            print(stat)
148
149
    # Shutdown
150
    mode.end()
151
152
153
def main():
154
    """Main entry point for Glances.
155
156
    Select the mode (standalone, client or server)
157
    Run it...
158
    """
159
    # SIGHUP not available on Windows (see issue #2408)
160
    if sys.platform.startswith('win'):
161
        signal_list = (signal.SIGTERM, signal.SIGINT)
162
    else:
163
        signal_list = (signal.SIGTERM, signal.SIGINT, signal.SIGHUP)
164
    # Catch the kill signal
165
    for sig in signal_list:
166
        signal.signal(sig, __signal_handler)
167
168
    # Log Glances and psutil version
169
    logger.info('Start Glances {}'.format(__version__))
170
    logger.info(
171
        '{} {} ({}) and psutil {} detected'.format(
172
            platform.python_implementation(), platform.python_version(), sys.executable, psutil_version
173
        )
174
    )
175
176
    # Share global var
177
    global core
178
179
    # Create the Glances main instance
180
    # Glances options from the command line are read first (in __init__)
181
    # then the options from the config file (in parse_args)
182
    core = GlancesMain()
183
184
    # Glances can be ran in standalone, client or server mode
185
    start(config=core.get_config(), args=core.get_args())
186