~mozillateam/mozilla-build-system/beta

« back to all changes in this revision

Viewing changes to python/psutil/psutil/__init__.py

  • Committer: Chris Coulson
  • Date: 2013-04-17 12:14:31 UTC
  • Revision ID: chris.coulson@canonical.com-20130417121431-90vvrxwi3go2hl3d
* Don't include unnecessary Makefiles
* Include the whole of python/
* Include .gdbinit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
#
 
4
# $Id: __init__.py 1525 2012-08-16 16:32:03Z g.rodola $
 
5
#
 
6
# Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
 
7
# Use of this source code is governed by a BSD-style license that can be
 
8
# found in the LICENSE file.
 
9
 
 
10
"""psutil is a module providing convenience functions for managing
 
11
processes and gather system information in a portable way by using
 
12
Python.
 
13
"""
 
14
 
 
15
from __future__ import division
 
16
 
 
17
__version__ = "0.6.1"
 
18
version_info = tuple([int(num) for num in __version__.split('.')])
 
19
 
 
20
__all__ = [
 
21
    # exceptions
 
22
    "Error", "NoSuchProcess", "AccessDenied", "TimeoutExpired",
 
23
    # constants
 
24
    "NUM_CPUS", "TOTAL_PHYMEM", "BOOT_TIME",
 
25
    "version_info", "__version__",
 
26
    "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
 
27
    "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
 
28
    "STATUS_WAKING", "STATUS_LOCKED",
 
29
    # classes
 
30
    "Process", "Popen",
 
31
    # functions
 
32
    "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list",
 
33
    "virtual_memory", "swap_memory",
 
34
    "cpu_times", "cpu_percent", "per_cpu_percent",
 
35
    "network_io_counters", "disk_io_counters",
 
36
    ]
 
37
 
 
38
import sys
 
39
import os
 
40
import time
 
41
import signal
 
42
import warnings
 
43
import errno
 
44
import subprocess
 
45
try:
 
46
    import pwd
 
47
except ImportError:
 
48
    pwd = None
 
49
 
 
50
from psutil.error import Error, NoSuchProcess, AccessDenied, TimeoutExpired
 
51
from psutil._compat import property, callable, defaultdict
 
52
from psutil._common import cached_property
 
53
from psutil._common import (deprecated as _deprecated,
 
54
                            nt_disk_iostat as _nt_disk_iostat,
 
55
                            nt_net_iostat as _nt_net_iostat,
 
56
                            nt_sysmeminfo as _nt_sysmeminfo,
 
57
                            isfile_strict as _isfile_strict)
 
58
from psutil._common import (STATUS_RUNNING, STATUS_IDLE, STATUS_SLEEPING,
 
59
                            STATUS_DISK_SLEEP, STATUS_STOPPED,
 
60
                            STATUS_TRACING_STOP, STATUS_ZOMBIE, STATUS_DEAD,
 
61
                            STATUS_WAKING, STATUS_LOCKED)
 
62
 
 
63
# import the appropriate module for our platform only
 
64
if sys.platform.startswith("linux"):
 
65
    import psutil._pslinux as _psplatform
 
66
    from psutil._pslinux import (phymem_buffers,
 
67
                                 cached_phymem,
 
68
                                 IOPRIO_CLASS_NONE,
 
69
                                 IOPRIO_CLASS_RT,
 
70
                                 IOPRIO_CLASS_BE,
 
71
                                 IOPRIO_CLASS_IDLE)
 
72
    phymem_buffers = _psplatform.phymem_buffers
 
73
    cached_phymem = _psplatform.cached_phymem
 
74
 
 
75
elif sys.platform.startswith("win32"):
 
76
    import psutil._psmswindows as _psplatform
 
77
    from psutil._psmswindows import (ABOVE_NORMAL_PRIORITY_CLASS,
 
78
                                     BELOW_NORMAL_PRIORITY_CLASS,
 
79
                                     HIGH_PRIORITY_CLASS,
 
80
                                     IDLE_PRIORITY_CLASS,
 
81
                                     NORMAL_PRIORITY_CLASS,
 
82
                                     REALTIME_PRIORITY_CLASS)
 
83
 
 
84
elif sys.platform.startswith("darwin"):
 
85
    import psutil._psosx as _psplatform
 
86
 
 
87
elif sys.platform.startswith("freebsd"):
 
88
    import psutil._psbsd as _psplatform
 
89
 
 
90
else:
 
91
    raise NotImplementedError('platform %s is not supported' % sys.platform)
 
92
 
 
93
__all__.extend(_psplatform.__extra__all__)
 
94
 
 
95
NUM_CPUS = _psplatform.NUM_CPUS
 
96
BOOT_TIME = _psplatform.BOOT_TIME
 
97
TOTAL_PHYMEM = _psplatform.TOTAL_PHYMEM
 
98
 
 
99
 
 
100
class Process(object):
 
101
    """Represents an OS process."""
 
102
 
 
103
    def __init__(self, pid):
 
104
        """Create a new Process object for the given pid.
 
105
        Raises NoSuchProcess if pid does not exist.
 
106
        """
 
107
        self._pid = pid
 
108
        self._gone = False
 
109
        # platform-specific modules define an _psplatform.Process
 
110
        # implementation class
 
111
        self._platform_impl = _psplatform.Process(pid)
 
112
        self._last_sys_cpu_times = None
 
113
        self._last_proc_cpu_times = None
 
114
        # cache creation time for later use in is_running() method
 
115
        try:
 
116
            self.create_time
 
117
        except AccessDenied:
 
118
            pass
 
119
        except NoSuchProcess:
 
120
            raise NoSuchProcess(pid, None, 'no process found with pid %s' % pid)
 
121
 
 
122
    def __str__(self):
 
123
        try:
 
124
            pid = self.pid
 
125
            name = repr(self.name)
 
126
        except NoSuchProcess:
 
127
            details = "(pid=%s (terminated))" % self.pid
 
128
        except AccessDenied:
 
129
            details = "(pid=%s)" % (self.pid)
 
130
        else:
 
131
            details = "(pid=%s, name=%s)" % (pid, name)
 
132
        return "%s.%s%s" % (self.__class__.__module__,
 
133
                            self.__class__.__name__, details)
 
134
 
 
135
    def __repr__(self):
 
136
        return "<%s at %s>" % (self.__str__(), id(self))
 
137
 
 
138
    def as_dict(self, attrs=[], ad_value=None):
 
139
        """Utility method returning process information as a hashable
 
140
        dictionary.
 
141
 
 
142
        If 'attrs' is specified it must be a list of strings reflecting
 
143
        available Process class's attribute names (e.g. ['get_cpu_times',
 
144
        'name']) else all public (read only) attributes are assumed.
 
145
 
 
146
        'ad_value' is the value which gets assigned to a dict key in case
 
147
        AccessDenied exception is raised when retrieving that particular
 
148
        process information.
 
149
        """
 
150
        excluded_names = set(['send_signal', 'suspend', 'resume', 'terminate',
 
151
                              'kill', 'wait', 'is_running', 'as_dict', 'parent',
 
152
                              'get_children', 'nice'])
 
153
        retdict = dict()
 
154
        for name in set(attrs or dir(self)):
 
155
            if name.startswith('_'):
 
156
                continue
 
157
            if name.startswith('set_'):
 
158
                continue
 
159
            if name in excluded_names:
 
160
                continue
 
161
            try:
 
162
                attr = getattr(self, name)
 
163
                if callable(attr):
 
164
                    if name == 'get_cpu_percent':
 
165
                        ret = attr(interval=0)
 
166
                    else:
 
167
                        ret = attr()
 
168
                else:
 
169
                    ret = attr
 
170
            except AccessDenied:
 
171
                ret = ad_value
 
172
            except NotImplementedError:
 
173
                # in case of not implemented functionality (may happen
 
174
                # on old or exotic systems) we want to crash only if
 
175
                # the user explicitly asked for that particular attr
 
176
                if attrs:
 
177
                    raise
 
178
                continue
 
179
            if name.startswith('get'):
 
180
                if name[3] == '_':
 
181
                    name = name[4:]
 
182
                elif name == 'getcwd':
 
183
                    name = 'cwd'
 
184
            retdict[name] = ret
 
185
        return retdict
 
186
 
 
187
    @property
 
188
    def pid(self):
 
189
        """The process pid."""
 
190
        return self._pid
 
191
 
 
192
    @cached_property
 
193
    def ppid(self):
 
194
        """The process parent pid."""
 
195
        return self._platform_impl.get_process_ppid()
 
196
 
 
197
    @property
 
198
    def parent(self):
 
199
        """Return the parent process as a Process object. If no parent
 
200
        pid is known return None.
 
201
        """
 
202
        ppid = self.ppid
 
203
        if ppid is not None:
 
204
            try:
 
205
                return Process(ppid)
 
206
            except NoSuchProcess:
 
207
                pass
 
208
 
 
209
    @cached_property
 
210
    def name(self):
 
211
        """The process name."""
 
212
        name = self._platform_impl.get_process_name()
 
213
        if os.name == 'posix':
 
214
            # On UNIX the name gets truncated to the first 15 characters.
 
215
            # If it matches the first part of the cmdline we return that
 
216
            # one instead because it's usually more explicative.
 
217
            # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon".
 
218
            try:
 
219
                cmdline = self.cmdline
 
220
            except AccessDenied:
 
221
                pass
 
222
            else:
 
223
                if cmdline:
 
224
                    extended_name = os.path.basename(cmdline[0])
 
225
                    if extended_name.startswith(name):
 
226
                        name = extended_name
 
227
        # XXX - perhaps needs refactoring
 
228
        self._platform_impl._process_name = name
 
229
        return name
 
230
 
 
231
    @cached_property
 
232
    def exe(self):
 
233
        """The process executable path. May also be an empty string."""
 
234
        def guess_it(fallback):
 
235
            # try to guess exe from cmdline[0] in absence of a native
 
236
            # exe representation
 
237
            cmdline = self.cmdline
 
238
            if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'):
 
239
                exe = cmdline[0]  # the possible exe
 
240
                rexe = os.path.realpath(exe)  # ...in case it's a symlink
 
241
                if os.path.isabs(rexe) and os.path.isfile(rexe) \
 
242
                and os.access(rexe, os.X_OK):
 
243
                    return exe
 
244
            if isinstance(fallback, AccessDenied):
 
245
                raise fallback
 
246
            return fallback
 
247
 
 
248
        try:
 
249
            exe = self._platform_impl.get_process_exe()
 
250
        except AccessDenied:
 
251
            err = sys.exc_info()[1]
 
252
            return guess_it(fallback=err)
 
253
        else:
 
254
            if not exe:
 
255
                # underlying implementation can legitimately return an
 
256
                # empty string; if that's the case we don't want to
 
257
                # raise AD while guessing from the cmdline
 
258
                try:
 
259
                    exe = guess_it(fallback=exe)
 
260
                except AccessDenied:
 
261
                    pass
 
262
            return exe
 
263
 
 
264
    @cached_property
 
265
    def cmdline(self):
 
266
        """The command line process has been called with."""
 
267
        return self._platform_impl.get_process_cmdline()
 
268
 
 
269
    @property
 
270
    def status(self):
 
271
        """The process current status as a STATUS_* constant."""
 
272
        return self._platform_impl.get_process_status()
 
273
 
 
274
    if os.name == 'posix':
 
275
 
 
276
        @property
 
277
        def uids(self):
 
278
            """Return a named tuple denoting the process real,
 
279
            effective, and saved user ids.
 
280
            """
 
281
            return self._platform_impl.get_process_uids()
 
282
 
 
283
        @property
 
284
        def gids(self):
 
285
            """Return a named tuple denoting the process real,
 
286
            effective, and saved group ids.
 
287
            """
 
288
            return self._platform_impl.get_process_gids()
 
289
 
 
290
        @property
 
291
        def terminal(self):
 
292
            """The terminal associated with this process, if any,
 
293
            else None.
 
294
            """
 
295
            return self._platform_impl.get_process_terminal()
 
296
 
 
297
    @property
 
298
    def username(self):
 
299
        """The name of the user that owns the process.
 
300
        On UNIX this is calculated by using *real* process uid.
 
301
        """
 
302
        if os.name == 'posix':
 
303
            if pwd is None:
 
304
                # might happen if python was installed from sources
 
305
                raise ImportError("requires pwd module shipped with standard python")
 
306
            return pwd.getpwuid(self.uids.real).pw_name
 
307
        else:
 
308
            return self._platform_impl.get_process_username()
 
309
 
 
310
    @cached_property
 
311
    def create_time(self):
 
312
        """The process creation time as a floating point number
 
313
        expressed in seconds since the epoch, in UTC.
 
314
        """
 
315
        return self._platform_impl.get_process_create_time()
 
316
 
 
317
    def getcwd(self):
 
318
        """Return a string representing the process current working
 
319
        directory.
 
320
        """
 
321
        return self._platform_impl.get_process_cwd()
 
322
 
 
323
    # Linux, BSD and Windows only
 
324
    if hasattr(_psplatform.Process, "get_process_io_counters"):
 
325
 
 
326
        def get_io_counters(self):
 
327
            """Return process I/O statistics as a namedtuple including
 
328
            the number of read/write calls performed and the amount of
 
329
            bytes read and written by the process.
 
330
            """
 
331
            return self._platform_impl.get_process_io_counters()
 
332
 
 
333
    def get_nice(self):
 
334
        """Get process niceness (priority)."""
 
335
        return self._platform_impl.get_process_nice()
 
336
 
 
337
    def set_nice(self, value):
 
338
        """Set process niceness (priority)."""
 
339
        return self._platform_impl.set_process_nice(value)
 
340
 
 
341
    # available only on Linux
 
342
    if hasattr(_psplatform.Process, "get_process_ionice"):
 
343
 
 
344
        def get_ionice(self):
 
345
            """Return process I/O niceness (priority) as a namedtuple."""
 
346
            return self._platform_impl.get_process_ionice()
 
347
 
 
348
        def set_ionice(self, ioclass, value=None):
 
349
            """Set process I/O niceness (priority).
 
350
            ioclass is one of the IOPRIO_CLASS_* constants.
 
351
            iodata is a number which goes from 0 to 7. The higher the
 
352
            value, the lower the I/O priority of the process.
 
353
            """
 
354
            return self._platform_impl.set_process_ionice(ioclass, value)
 
355
 
 
356
    # available on Windows and Linux only
 
357
    if hasattr(_psplatform.Process, "get_process_cpu_affinity"):
 
358
 
 
359
        def get_cpu_affinity(self):
 
360
            """Get process current CPU affinity."""
 
361
            return self._platform_impl.get_process_cpu_affinity()
 
362
 
 
363
        def set_cpu_affinity(self, cpus):
 
364
            """Set process current CPU affinity.
 
365
            'cpus' is a list of CPUs for which you want to set the
 
366
            affinity (e.g. [0, 1]).
 
367
            """
 
368
            return self._platform_impl.set_process_cpu_affinity(cpus)
 
369
 
 
370
    if os.name == 'nt':
 
371
 
 
372
        def get_num_handles(self):
 
373
            """Return the number of handles opened by this process
 
374
            (Windows only).
 
375
            """
 
376
            return self._platform_impl.get_num_handles()
 
377
 
 
378
    if os.name == 'posix':
 
379
 
 
380
        def get_num_fds(self):
 
381
            """Return the number of file descriptors opened by this
 
382
            process (POSIX only).
 
383
            """
 
384
            return self._platform_impl.get_num_fds()
 
385
 
 
386
    def get_num_ctx_switches(self):
 
387
        """Return the number voluntary and involuntary context switches
 
388
        performed by this process.
 
389
        """
 
390
        return self._platform_impl.get_num_ctx_switches()
 
391
 
 
392
    def get_num_threads(self):
 
393
        """Return the number of threads used by this process."""
 
394
        return self._platform_impl.get_process_num_threads()
 
395
 
 
396
    def get_threads(self):
 
397
        """Return threads opened by process as a list of namedtuples
 
398
        including thread id and thread CPU times (user/system).
 
399
        """
 
400
        return self._platform_impl.get_process_threads()
 
401
 
 
402
    def get_children(self, recursive=False):
 
403
        """Return the children of this process as a list of Process
 
404
        objects.
 
405
        If recursive is True return all the parent descendants.
 
406
 
 
407
        Example (A == this process):
 
408
 
 
409
         A ─┐
 
410
            │
 
411
            ├─ B (child) ─┐
 
412
            │             └─ X (grandchild) ─┐
 
413
            │                                └─ Y (great grandchild)
 
414
            ├─ C (child)
 
415
            └─ D (child)
 
416
 
 
417
        >>> p.get_children()
 
418
        B, C, D
 
419
        >>> p.get_children(recursive=True)
 
420
        B, X, Y, C, D
 
421
 
 
422
        Note that in the example above if process X disappears
 
423
        process Y won't be returned either as the reference to
 
424
        process A is lost.
 
425
        """
 
426
        if not self.is_running():
 
427
            name = self._platform_impl._process_name
 
428
            raise NoSuchProcess(self.pid, name)
 
429
 
 
430
        ret = []
 
431
        if not recursive:
 
432
            for p in process_iter():
 
433
                try:
 
434
                    if p.ppid == self.pid:
 
435
                        # if child happens to be older than its parent
 
436
                        # (self) it means child's PID has been reused
 
437
                        if self.create_time <= p.create_time:
 
438
                            ret.append(p)
 
439
                except NoSuchProcess:
 
440
                    pass
 
441
        else:
 
442
            # construct a dict where 'values' are all the processes
 
443
            # having 'key' as their parent
 
444
            table = defaultdict(list)
 
445
            for p in process_iter():
 
446
                try:
 
447
                    table[p.ppid].append(p)
 
448
                except NoSuchProcess:
 
449
                    pass
 
450
            # At this point we have a mapping table where table[self.pid]
 
451
            # are the current process's children.
 
452
            # Below, we look for all descendants recursively, similarly
 
453
            # to a recursive function call.
 
454
            checkpids = [self.pid]
 
455
            for pid in checkpids:
 
456
                for child in table[pid]:
 
457
                    try:
 
458
                        # if child happens to be older than its parent
 
459
                        # (self) it means child's PID has been reused
 
460
                        intime = self.create_time <= child.create_time
 
461
                    except NoSuchProcess:
 
462
                        pass
 
463
                    else:
 
464
                        if intime:
 
465
                            ret.append(child)
 
466
                            if child.pid not in checkpids:
 
467
                                checkpids.append(child.pid)
 
468
        return ret
 
469
 
 
470
    def get_cpu_percent(self, interval=0.1):
 
471
        """Return a float representing the current process CPU
 
472
        utilization as a percentage.
 
473
 
 
474
        When interval is > 0.0 compares process times to system CPU
 
475
        times elapsed before and after the interval (blocking).
 
476
 
 
477
        When interval is 0.0 or None compares process times to system CPU
 
478
        times elapsed since last call, returning immediately.
 
479
        In this case is recommended for accuracy that this function be
 
480
        called with at least 0.1 seconds between calls.
 
481
        """
 
482
        blocking = interval is not None and interval > 0.0
 
483
        if blocking:
 
484
            st1 = sum(cpu_times())
 
485
            pt1 = self._platform_impl.get_cpu_times()
 
486
            time.sleep(interval)
 
487
            st2 = sum(cpu_times())
 
488
            pt2 = self._platform_impl.get_cpu_times()
 
489
        else:
 
490
            st1 = self._last_sys_cpu_times
 
491
            pt1 = self._last_proc_cpu_times
 
492
            st2 = sum(cpu_times())
 
493
            pt2 = self._platform_impl.get_cpu_times()
 
494
            if st1 is None or pt1 is None:
 
495
                self._last_sys_cpu_times = st2
 
496
                self._last_proc_cpu_times = pt2
 
497
                return 0.0
 
498
 
 
499
        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
 
500
        delta_time = st2 - st1
 
501
        # reset values for next call in case of interval == None
 
502
        self._last_sys_cpu_times = st2
 
503
        self._last_proc_cpu_times = pt2
 
504
 
 
505
        try:
 
506
            # the utilization split between all CPUs
 
507
            overall_percent = (delta_proc / delta_time) * 100
 
508
        except ZeroDivisionError:
 
509
            # interval was too low
 
510
            return 0.0
 
511
        # the utilization of a single CPU
 
512
        single_cpu_percent = overall_percent * NUM_CPUS
 
513
        # on posix a percentage > 100 is legitimate
 
514
        # http://stackoverflow.com/questions/1032357/comprehending-top-cpu-usage
 
515
        # on windows we use this ugly hack to avoid troubles with float
 
516
        # precision issues
 
517
        if os.name != 'posix':
 
518
            if single_cpu_percent > 100.0:
 
519
                return 100.0
 
520
        return round(single_cpu_percent, 1)
 
521
 
 
522
    def get_cpu_times(self):
 
523
        """Return a tuple whose values are process CPU user and system
 
524
        times. The same as os.times() but per-process.
 
525
        """
 
526
        return self._platform_impl.get_cpu_times()
 
527
 
 
528
    def get_memory_info(self):
 
529
        """Return a tuple representing RSS (Resident Set Size) and VMS
 
530
        (Virtual Memory Size) in bytes.
 
531
 
 
532
        On UNIX RSS and VMS are the same values shown by ps.
 
533
 
 
534
        On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns
 
535
        of taskmgr.exe.
 
536
        """
 
537
        return self._platform_impl.get_memory_info()
 
538
 
 
539
    def get_ext_memory_info(self):
 
540
        """Return a namedtuple with variable fields depending on the
 
541
        platform representing extended memory information about
 
542
        the process. All numbers are expressed in bytes.
 
543
        """
 
544
        return self._platform_impl.get_ext_memory_info()
 
545
 
 
546
    def get_memory_percent(self):
 
547
        """Compare physical system memory to process resident memory and
 
548
        calculate process memory utilization as a percentage.
 
549
        """
 
550
        rss = self._platform_impl.get_memory_info()[0]
 
551
        try:
 
552
            return (rss / float(TOTAL_PHYMEM)) * 100
 
553
        except ZeroDivisionError:
 
554
            return 0.0
 
555
 
 
556
    def get_memory_maps(self, grouped=True):
 
557
        """Return process's mapped memory regions as a list of nameduples
 
558
        whose fields are variable depending on the platform.
 
559
 
 
560
        If 'grouped' is True the mapped regions with the same 'path'
 
561
        are grouped together and the different memory fields are summed.
 
562
 
 
563
        If 'grouped' is False every mapped region is shown as a single
 
564
        entity and the namedtuple will also include the mapped region's
 
565
        address space ('addr') and permission set ('perms').
 
566
        """
 
567
        it = self._platform_impl.get_memory_maps()
 
568
        if grouped:
 
569
            d = {}
 
570
            for tupl in it:
 
571
                path = tupl[2]
 
572
                nums = tupl[3:]
 
573
                try:
 
574
                    d[path] = map(lambda x, y: x+y, d[path], nums)
 
575
                except KeyError:
 
576
                    d[path] = nums
 
577
            nt = self._platform_impl.nt_mmap_grouped
 
578
            return [nt(path, *d[path]) for path in d]
 
579
        else:
 
580
            nt = self._platform_impl.nt_mmap_ext
 
581
            return [nt(*x) for x in it]
 
582
 
 
583
    def get_open_files(self):
 
584
        """Return files opened by process as a list of namedtuples
 
585
        including absolute file name and file descriptor number.
 
586
        """
 
587
        return self._platform_impl.get_open_files()
 
588
 
 
589
    def get_connections(self, kind='inet'):
 
590
        """Return connections opened by process as a list of namedtuples.
 
591
        The kind parameter filters for connections that fit the following
 
592
        criteria:
 
593
 
 
594
        Kind Value      Connections using
 
595
        inet            IPv4 and IPv6
 
596
        inet4           IPv4
 
597
        inet6           IPv6
 
598
        tcp             TCP
 
599
        tcp4            TCP over IPv4
 
600
        tcp6            TCP over IPv6
 
601
        udp             UDP
 
602
        udp4            UDP over IPv4
 
603
        udp6            UDP over IPv6
 
604
        unix            UNIX socket (both UDP and TCP protocols)
 
605
        all             the sum of all the possible families and protocols
 
606
        """
 
607
        return self._platform_impl.get_connections(kind)
 
608
 
 
609
    def is_running(self):
 
610
        """Return whether this process is running."""
 
611
        if self._gone:
 
612
            return False
 
613
        try:
 
614
            # Checking if pid is alive is not enough as the pid might
 
615
            # have been reused by another process.
 
616
            # pid + creation time, on the other hand, is supposed to
 
617
            # identify a process univocally.
 
618
            return self.create_time == \
 
619
                   self._platform_impl.get_process_create_time()
 
620
        except NoSuchProcess:
 
621
            self._gone = True
 
622
            return False
 
623
 
 
624
    def send_signal(self, sig):
 
625
        """Send a signal to process (see signal module constants).
 
626
        On Windows only SIGTERM is valid and is treated as an alias
 
627
        for kill().
 
628
        """
 
629
        # safety measure in case the current process has been killed in
 
630
        # meantime and the kernel reused its PID
 
631
        if not self.is_running():
 
632
            name = self._platform_impl._process_name
 
633
            raise NoSuchProcess(self.pid, name)
 
634
        if os.name == 'posix':
 
635
            try:
 
636
                os.kill(self.pid, sig)
 
637
            except OSError:
 
638
                err = sys.exc_info()[1]
 
639
                name = self._platform_impl._process_name
 
640
                if err.errno == errno.ESRCH:
 
641
                    raise NoSuchProcess(self.pid, name)
 
642
                if err.errno == errno.EPERM:
 
643
                    raise AccessDenied(self.pid, name)
 
644
                raise
 
645
        else:
 
646
            if sig == signal.SIGTERM:
 
647
                self._platform_impl.kill_process()
 
648
            else:
 
649
                raise ValueError("only SIGTERM is supported on Windows")
 
650
 
 
651
    def suspend(self):
 
652
        """Suspend process execution."""
 
653
        # safety measure in case the current process has been killed in
 
654
        # meantime and the kernel reused its PID
 
655
        if not self.is_running():
 
656
            name = self._platform_impl._process_name
 
657
            raise NoSuchProcess(self.pid, name)
 
658
        # windows
 
659
        if hasattr(self._platform_impl, "suspend_process"):
 
660
            self._platform_impl.suspend_process()
 
661
        else:
 
662
            # posix
 
663
            self.send_signal(signal.SIGSTOP)
 
664
 
 
665
    def resume(self):
 
666
        """Resume process execution."""
 
667
        # safety measure in case the current process has been killed in
 
668
        # meantime and the kernel reused its PID
 
669
        if not self.is_running():
 
670
            name = self._platform_impl._process_name
 
671
            raise NoSuchProcess(self.pid, name)
 
672
        # windows
 
673
        if hasattr(self._platform_impl, "resume_process"):
 
674
            self._platform_impl.resume_process()
 
675
        else:
 
676
            # posix
 
677
            self.send_signal(signal.SIGCONT)
 
678
 
 
679
    def terminate(self):
 
680
        """Terminate the process with SIGTERM.
 
681
        On Windows this is an alias for kill().
 
682
        """
 
683
        self.send_signal(signal.SIGTERM)
 
684
 
 
685
    def kill(self):
 
686
        """Kill the current process."""
 
687
        # safety measure in case the current process has been killed in
 
688
        # meantime and the kernel reused its PID
 
689
        if not self.is_running():
 
690
            name = self._platform_impl._process_name
 
691
            raise NoSuchProcess(self.pid, name)
 
692
        if os.name == 'posix':
 
693
            self.send_signal(signal.SIGKILL)
 
694
        else:
 
695
            self._platform_impl.kill_process()
 
696
 
 
697
    def wait(self, timeout=None):
 
698
        """Wait for process to terminate and, if process is a children
 
699
        of the current one also return its exit code, else None.
 
700
        """
 
701
        if timeout is not None and not timeout >= 0:
 
702
            raise ValueError("timeout must be a positive integer")
 
703
        return self._platform_impl.process_wait(timeout)
 
704
 
 
705
    # --- deprecated API
 
706
 
 
707
    @property
 
708
    def nice(self):
 
709
        """Get or set process niceness (priority).
 
710
        Deprecated, use get_nice() instead.
 
711
        """
 
712
        msg = "this property is deprecated; use Process.get_nice() method instead"
 
713
        warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
 
714
        return self.get_nice()
 
715
 
 
716
    @nice.setter
 
717
    def nice(self, value):
 
718
        # invoked on "p.nice = num"; change process niceness
 
719
        # deprecated in favor of set_nice()
 
720
        msg = "this property is deprecated; use Process.set_nice() method instead"
 
721
        warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
 
722
        return self.set_nice(value)
 
723
 
 
724
 
 
725
class Popen(Process):
 
726
    """A more convenient interface to stdlib subprocess module.
 
727
    It starts a sub process and deals with it exactly as when using
 
728
    subprocess.Popen class but in addition also provides all the
 
729
    property and methods of psutil.Process class in a single interface:
 
730
 
 
731
      >>> import psutil
 
732
      >>> from subprocess import PIPE
 
733
      >>> p = psutil.Popen(["/usr/bin/python", "-c", "print 'hi'"], stdout=PIPE)
 
734
      >>> p.name
 
735
      'python'
 
736
      >>> p.uids
 
737
      user(real=1000, effective=1000, saved=1000)
 
738
      >>> p.username
 
739
      'giampaolo'
 
740
      >>> p.communicate()
 
741
      ('hi\n', None)
 
742
      >>> p.terminate()
 
743
      >>> p.wait(timeout=2)
 
744
      0
 
745
      >>>
 
746
 
 
747
    For method names common to both classes such as kill(), terminate()
 
748
    and wait(), psutil.Process implementation takes precedence.
 
749
 
 
750
    For a complete documentation refers to:
 
751
    http://docs.python.org/library/subprocess.html
 
752
    """
 
753
 
 
754
    def __init__(self, *args, **kwargs):
 
755
        self.__subproc = subprocess.Popen(*args, **kwargs)
 
756
        self._pid = self.__subproc.pid
 
757
        self._gone = False
 
758
        self._platform_impl = _psplatform.Process(self._pid)
 
759
        self._last_sys_cpu_times = None
 
760
        self._last_proc_cpu_times = None
 
761
        try:
 
762
            self.create_time
 
763
        except AccessDenied:
 
764
            pass
 
765
        except NoSuchProcess:
 
766
            raise NoSuchProcess(self._pid, None,
 
767
                                "no process found with pid %s" % pid)
 
768
 
 
769
    def __dir__(self):
 
770
        return list(set(dir(Popen) + dir(subprocess.Popen)))
 
771
 
 
772
    def __getattribute__(self, name):
 
773
        try:
 
774
            return object.__getattribute__(self, name)
 
775
        except AttributeError:
 
776
            try:
 
777
                return object.__getattribute__(self.__subproc, name)
 
778
            except AttributeError:
 
779
                raise AttributeError("%s instance has no attribute '%s'"
 
780
                                      %(self.__class__.__name__, name))
 
781
 
 
782
 
 
783
# =====================================================================
 
784
# --- system processes related functions
 
785
# =====================================================================
 
786
 
 
787
get_pid_list = _psplatform.get_pid_list
 
788
pid_exists = _psplatform.pid_exists
 
789
 
 
790
_pmap = {}
 
791
 
 
792
def process_iter():
 
793
    """Return a generator yielding a Process class instance for all
 
794
    running processes on the local machine.
 
795
 
 
796
    Every new Process instance is only created once and then cached
 
797
    into an internal table which is updated every time this is used.
 
798
 
 
799
    The sorting order in which processes are yielded is based on
 
800
    their PIDs.
 
801
    """
 
802
    def add(pid):
 
803
        proc = Process(pid)
 
804
        _pmap[proc.pid] = proc
 
805
        return proc
 
806
 
 
807
    def remove(pid):
 
808
        _pmap.pop(pid, None)
 
809
 
 
810
    a = set(get_pid_list())
 
811
    b = set(_pmap.keys())
 
812
    new_pids = a - b
 
813
    gone_pids = b - a
 
814
 
 
815
    for pid in gone_pids:
 
816
        remove(pid)
 
817
    for pid, proc in sorted(list(_pmap.items()) + \
 
818
                            list(dict.fromkeys(new_pids).items())):
 
819
        try:
 
820
            if proc is None:  # new process
 
821
                yield add(pid)
 
822
            else:
 
823
                # use is_running() to check whether PID has been reused by
 
824
                # another process in which case yield a new Process instance
 
825
                if proc.is_running():
 
826
                    yield proc
 
827
                else:
 
828
                    yield add(pid)
 
829
        except NoSuchProcess:
 
830
            remove(pid)
 
831
        except AccessDenied:
 
832
            # Process creation time can't be determined hence there's
 
833
            # no way to tell whether the pid of the cached process
 
834
            # has been reused. Just return the cached version.
 
835
            yield proc
 
836
 
 
837
# =====================================================================
 
838
# --- CPU related functions
 
839
# =====================================================================
 
840
 
 
841
def cpu_times(percpu=False):
 
842
    """Return system-wide CPU times as a namedtuple object.
 
843
    Every CPU time represents the time CPU has spent in the given mode.
 
844
    The attributes availability varies depending on the platform.
 
845
    Here follows a list of all available attributes:
 
846
     - user
 
847
     - system
 
848
     - idle
 
849
     - nice (UNIX)
 
850
     - iowait (Linux)
 
851
     - irq (Linux, FreeBSD)
 
852
     - softirq (Linux)
 
853
 
 
854
    When percpu is True return a list of nameduples for each CPU.
 
855
    First element of the list refers to first CPU, second element
 
856
    to second CPU and so on.
 
857
    The order of the list is consistent across calls.
 
858
    """
 
859
    if not percpu:
 
860
        return _psplatform.get_system_cpu_times()
 
861
    else:
 
862
        return _psplatform.get_system_per_cpu_times()
 
863
 
 
864
 
 
865
_last_cpu_times = cpu_times()
 
866
_last_per_cpu_times = cpu_times(percpu=True)
 
867
 
 
868
def cpu_percent(interval=0.1, percpu=False):
 
869
    """Return a float representing the current system-wide CPU
 
870
    utilization as a percentage.
 
871
 
 
872
    When interval is > 0.0 compares system CPU times elapsed before
 
873
    and after the interval (blocking).
 
874
 
 
875
    When interval is 0.0 or None compares system CPU times elapsed
 
876
    since last call or module import, returning immediately.
 
877
    In this case is recommended for accuracy that this function be
 
878
    called with at least 0.1 seconds between calls.
 
879
 
 
880
    When percpu is True returns a list of floats representing the
 
881
    utilization as a percentage for each CPU.
 
882
    First element of the list refers to first CPU, second element
 
883
    to second CPU and so on.
 
884
    The order of the list is consistent across calls.
 
885
    """
 
886
    global _last_cpu_times
 
887
    global _last_per_cpu_times
 
888
    blocking = interval is not None and interval > 0.0
 
889
 
 
890
    def calculate(t1, t2):
 
891
        t1_all = sum(t1)
 
892
        t1_busy = t1_all - t1.idle
 
893
 
 
894
        t2_all = sum(t2)
 
895
        t2_busy = t2_all - t2.idle
 
896
 
 
897
        # this usually indicates a float precision issue
 
898
        if t2_busy <= t1_busy:
 
899
            return 0.0
 
900
 
 
901
        busy_delta = t2_busy - t1_busy
 
902
        all_delta = t2_all - t1_all
 
903
        busy_perc = (busy_delta / all_delta) * 100
 
904
        return round(busy_perc, 1)
 
905
 
 
906
    # system-wide usage
 
907
    if not percpu:
 
908
        if blocking:
 
909
            t1 = cpu_times()
 
910
            time.sleep(interval)
 
911
        else:
 
912
            t1 = _last_cpu_times
 
913
        _last_cpu_times = cpu_times()
 
914
        return calculate(t1, _last_cpu_times)
 
915
    # per-cpu usage
 
916
    else:
 
917
        ret = []
 
918
        if blocking:
 
919
            tot1 = cpu_times(percpu=True)
 
920
            time.sleep(interval)
 
921
        else:
 
922
            tot1 = _last_per_cpu_times
 
923
        _last_per_cpu_times = cpu_times(percpu=True)
 
924
        for t1, t2 in zip(tot1, _last_per_cpu_times):
 
925
            ret.append(calculate(t1, t2))
 
926
        return ret
 
927
 
 
928
# =====================================================================
 
929
# --- system memory related functions
 
930
# =====================================================================
 
931
 
 
932
def virtual_memory():
 
933
    """Return statistics about system memory usage as a namedtuple
 
934
    including the following fields, expressed in bytes:
 
935
 
 
936
     - total:
 
937
       total physical memory available.
 
938
 
 
939
     - available:
 
940
       the actual amount of available memory that can be given
 
941
       instantly to processes that request more memory in bytes; this
 
942
       is calculated by summing different memory values depending on
 
943
       the platform (e.g. free + buffers + cached on Linux) and it is
 
944
       supposed to be used to monitor actual memory usage in a cross
 
945
       platform fashion.
 
946
 
 
947
     - percent:
 
948
       the percentage usage calculated as (total - available) / total * 100
 
949
 
 
950
     - used:
 
951
       memory used, calculated differently depending on the platform and
 
952
       designed for informational purposes only:
 
953
        OSX: active + inactive + wired
 
954
        BSD: active + wired + cached
 
955
        LINUX: total - free
 
956
 
 
957
     - free:
 
958
       memory not being used at all (zeroed) that is readily available;
 
959
       note that this doesn't reflect the actual memory available
 
960
       (use 'available' instead)
 
961
 
 
962
    Platform-specific fields:
 
963
 
 
964
     - active (UNIX):
 
965
       memory currently in use or very recently used, and so it is in RAM.
 
966
 
 
967
     - inactive (UNIX):
 
968
       memory that is marked as not used.
 
969
 
 
970
     - buffers (BSD, Linux):
 
971
       cache for things like file system metadata.
 
972
 
 
973
     - cached (BSD, OSX):
 
974
       cache for various things.
 
975
 
 
976
     - wired (OSX, BSD):
 
977
       memory that is marked to always stay in RAM. It is never moved to disk.
 
978
 
 
979
     - shared (BSD):
 
980
       memory that may be simultaneously accessed by multiple processes.
 
981
 
 
982
    The sum of 'used' and 'available' does not necessarily equal total.
 
983
    On Windows 'available' and 'free' are the same.
 
984
    """
 
985
    return _psplatform.virtual_memory()
 
986
 
 
987
def swap_memory():
 
988
    """Return system swap memory statistics as a namedtuple including
 
989
    the following attributes:
 
990
 
 
991
     - total:   total swap memory in bytes
 
992
     - used:    used swap memory in bytes
 
993
     - free:    free swap memory in bytes
 
994
     - percent: the percentage usage
 
995
     - sin:     no. of bytes the system has swapped in from disk (cumulative)
 
996
     - sout:    no. of bytes the system has swapped out from disk (cumulative)
 
997
 
 
998
    'sin' and 'sout' on Windows are meaningless and always set to 0.
 
999
    """
 
1000
    return _psplatform.swap_memory()
 
1001
 
 
1002
# =====================================================================
 
1003
# --- disks/paritions related functions
 
1004
# =====================================================================
 
1005
 
 
1006
def disk_usage(path):
 
1007
    """Return disk usage statistics about the given path as a namedtuple
 
1008
    including total, used and free space expressed in bytes plus the
 
1009
    percentage usage.
 
1010
    """
 
1011
    return _psplatform.get_disk_usage(path)
 
1012
 
 
1013
def disk_partitions(all=False):
 
1014
    """Return mounted partitions as a list of namedtuples including
 
1015
    device, mount point, filesystem type and mount options (a raw
 
1016
    string separated by commas which may vary depending on the platform).
 
1017
 
 
1018
    If "all" parameter is False return physical devices only and ignore
 
1019
    all others.
 
1020
    """
 
1021
    return _psplatform.disk_partitions(all)
 
1022
 
 
1023
def disk_io_counters(perdisk=False):
 
1024
    """Return system disk I/O statistics as a namedtuple including
 
1025
    the following attributes:
 
1026
 
 
1027
     - read_count:  number of reads
 
1028
     - write_count: number of writes
 
1029
     - read_bytes:  number of bytes read
 
1030
     - write_bytes: number of bytes written
 
1031
     - read_time:   time spent reading from disk (in milliseconds)
 
1032
     - write_time:  time spent writing to disk (in milliseconds)
 
1033
 
 
1034
    If perdisk is True return the same information for every
 
1035
    physical disk installed on the system as a dictionary
 
1036
    with partition names as the keys and the namedutuple
 
1037
    described above as the values.
 
1038
    """
 
1039
    rawdict = _psplatform.disk_io_counters()
 
1040
    if not rawdict:
 
1041
        raise RuntimeError("couldn't find any physical disk")
 
1042
    if perdisk:
 
1043
        for disk, fields in rawdict.items():
 
1044
            rawdict[disk] = _nt_disk_iostat(*fields)
 
1045
        return rawdict
 
1046
    else:
 
1047
        return _nt_disk_iostat(*[sum(x) for x in zip(*rawdict.values())])
 
1048
 
 
1049
# =====================================================================
 
1050
# --- network related functions
 
1051
# =====================================================================
 
1052
 
 
1053
def network_io_counters(pernic=False):
 
1054
    """Return network I/O statistics as a namedtuple including
 
1055
    the following attributes:
 
1056
 
 
1057
     - bytes_sent:   number of bytes sent
 
1058
     - bytes_recv:   number of bytes received
 
1059
     - packets_sent: number of packets sent
 
1060
     - packets_recv: number of packets received
 
1061
     - errin:        total number of errors while receiving
 
1062
     - errout:       total number of errors while sending
 
1063
     - dropin:       total number of incoming packets which were dropped
 
1064
     - dropout:      total number of outgoing packets which were dropped
 
1065
                     (always 0 on OSX and BSD)
 
1066
 
 
1067
    If pernic is True return the same information for every
 
1068
    network interface installed on the system as a dictionary
 
1069
    with network interface names as the keys and the namedtuple
 
1070
    described above as the values.
 
1071
    """
 
1072
    rawdict = _psplatform.network_io_counters()
 
1073
    if not rawdict:
 
1074
        raise RuntimeError("couldn't find any network interface")
 
1075
    if pernic:
 
1076
        for nic, fields in rawdict.items():
 
1077
            rawdict[nic] = _nt_net_iostat(*fields)
 
1078
        return rawdict
 
1079
    else:
 
1080
        return _nt_net_iostat(*[sum(x) for x in zip(*rawdict.values())])
 
1081
 
 
1082
# =====================================================================
 
1083
# --- other system related functions
 
1084
# =====================================================================
 
1085
 
 
1086
def get_users():
 
1087
    """Return users currently connected on the system as a list of
 
1088
    namedtuples including the following attributes.
 
1089
 
 
1090
     - user: the name of the user
 
1091
     - terminal: the tty or pseudo-tty associated with the user, if any.
 
1092
     - host: the host name associated with the entry, if any.
 
1093
     - started: the creation time as a floating point number expressed in
 
1094
       seconds since the epoch.
 
1095
    """
 
1096
    return _psplatform.get_system_users()
 
1097
 
 
1098
# =====================================================================
 
1099
# --- deprecated functions
 
1100
# =====================================================================
 
1101
 
 
1102
@_deprecated()
 
1103
def get_process_list():
 
1104
    """Return a list of Process class instances for all running
 
1105
    processes on the local machine (deprecated).
 
1106
    """
 
1107
    return list(process_iter())
 
1108
 
 
1109
@_deprecated()
 
1110
def phymem_usage():
 
1111
    """Return the amount of total, used and free physical memory
 
1112
    on the system in bytes plus the percentage usage.
 
1113
    Deprecated by psutil.virtual_memory().
 
1114
    """
 
1115
    mem = virtual_memory()
 
1116
    return _nt_sysmeminfo(mem.total, mem.used, mem.free, mem.percent)
 
1117
 
 
1118
@_deprecated("psutil.swap_memory()")
 
1119
def virtmem_usage():
 
1120
    return swap_memory()
 
1121
 
 
1122
@_deprecated("psutil.phymem_usage().free")
 
1123
def avail_phymem():
 
1124
    return phymem_usage().free
 
1125
 
 
1126
@_deprecated("psutil.phymem_usage().used")
 
1127
def used_phymem():
 
1128
    return phymem_usage().used
 
1129
 
 
1130
@_deprecated("psutil.virtmem_usage().total")
 
1131
def total_virtmem():
 
1132
    return virtmem_usage().total
 
1133
 
 
1134
@_deprecated("psutil.virtmem_usage().used")
 
1135
def used_virtmem():
 
1136
    return virtmem_usage().used
 
1137
 
 
1138
@_deprecated("psutil.virtmem_usage().free")
 
1139
def avail_virtmem():
 
1140
    return virtmem_usage().free
 
1141
 
 
1142
def test():
 
1143
    """List info of all currently running processes emulating ps aux
 
1144
    output.
 
1145
    """
 
1146
    import datetime
 
1147
    from psutil._compat import print_
 
1148
 
 
1149
    today_day = datetime.date.today()
 
1150
    templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s  %s"
 
1151
    attrs = ['pid', 'username', 'get_cpu_percent', 'get_memory_percent', 'name',
 
1152
             'get_cpu_times', 'create_time', 'get_memory_info']
 
1153
    if os.name == 'posix':
 
1154
        attrs.append('terminal')
 
1155
    print_(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY", "START",
 
1156
                    "TIME", "COMMAND"))
 
1157
    for p in sorted(process_iter(), key=lambda p: p.pid):
 
1158
        try:
 
1159
            pinfo = p.as_dict(attrs, ad_value='')
 
1160
        except NoSuchProcess:
 
1161
            pass
 
1162
        else:
 
1163
            if pinfo['create_time']:
 
1164
                ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
 
1165
                if ctime.date() == today_day:
 
1166
                    ctime = ctime.strftime("%H:%M")
 
1167
                else:
 
1168
                    ctime = ctime.strftime("%b%d")
 
1169
            cputime = time.strftime("%M:%S", time.localtime(sum(pinfo['cpu_times'])))
 
1170
            user = pinfo['username']
 
1171
            if os.name == 'nt' and '\\' in user:
 
1172
                user = user.split('\\')[1]
 
1173
            vms = pinfo['memory_info'] and \
 
1174
                  int(pinfo['memory_info'].vms / 1024) or '?'
 
1175
            rss = pinfo['memory_info'] and \
 
1176
                  int(pinfo['memory_info'].rss / 1024) or '?'
 
1177
            memp = pinfo['memory_percent'] and \
 
1178
                   round(pinfo['memory_percent'], 1) or '?'
 
1179
            print_(templ % (user[:10],
 
1180
                            pinfo['pid'],
 
1181
                            pinfo['cpu_percent'],
 
1182
                            memp,
 
1183
                            vms,
 
1184
                            rss,
 
1185
                            pinfo.get('terminal', '') or '?',
 
1186
                            ctime,
 
1187
                            cputime,
 
1188
                            pinfo['name'].strip() or '?'))
 
1189
 
 
1190
if __name__ == "__main__":
 
1191
    test()
 
1192
 
 
1193
del property, cached_property, division
 
1194
if sys.version_info < (3, 0):
 
1195
    del num