1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8"""psutil is a cross-platform library for retrieving information on
9running processes and system utilization (CPU, memory, disks, network)
10in Python.
11"""
12
13from __future__ import division
14
15import collections
16import errno
17import functools
18import os
19import signal
20import subprocess
21import sys
22import time
23try:
24    import pwd
25except ImportError:
26    pwd = None
27
28from . import _common
29from ._common import memoize
30from ._compat import callable, long
31from ._compat import PY3 as _PY3
32
33from ._common import (STATUS_RUNNING,  # NOQA
34                      STATUS_SLEEPING,
35                      STATUS_DISK_SLEEP,
36                      STATUS_STOPPED,
37                      STATUS_TRACING_STOP,
38                      STATUS_ZOMBIE,
39                      STATUS_DEAD,
40                      STATUS_WAKING,
41                      STATUS_LOCKED,
42                      STATUS_IDLE,  # bsd
43                      STATUS_WAITING)  # bsd
44
45from ._common import (CONN_ESTABLISHED,
46                      CONN_SYN_SENT,
47                      CONN_SYN_RECV,
48                      CONN_FIN_WAIT1,
49                      CONN_FIN_WAIT2,
50                      CONN_TIME_WAIT,
51                      CONN_CLOSE,
52                      CONN_CLOSE_WAIT,
53                      CONN_LAST_ACK,
54                      CONN_LISTEN,
55                      CONN_CLOSING,
56                      CONN_NONE)
57
58from ._common import (NIC_DUPLEX_FULL,  # NOQA
59                      NIC_DUPLEX_HALF,
60                      NIC_DUPLEX_UNKNOWN)
61
62if sys.platform.startswith("linux"):
63    from . import _pslinux as _psplatform
64
65    from ._pslinux import (IOPRIO_CLASS_NONE,  # NOQA
66                           IOPRIO_CLASS_RT,
67                           IOPRIO_CLASS_BE,
68                           IOPRIO_CLASS_IDLE)
69    # Linux >= 2.6.36
70    if _psplatform.HAS_PRLIMIT:
71        from ._psutil_linux import (RLIM_INFINITY,  # NOQA
72                                    RLIMIT_AS,
73                                    RLIMIT_CORE,
74                                    RLIMIT_CPU,
75                                    RLIMIT_DATA,
76                                    RLIMIT_FSIZE,
77                                    RLIMIT_LOCKS,
78                                    RLIMIT_MEMLOCK,
79                                    RLIMIT_NOFILE,
80                                    RLIMIT_NPROC,
81                                    RLIMIT_RSS,
82                                    RLIMIT_STACK)
83        # Kinda ugly but considerably faster than using hasattr() and
84        # setattr() against the module object (we are at import time:
85        # speed matters).
86        from . import _psutil_linux
87        try:
88            RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE
89        except AttributeError:
90            pass
91        try:
92            RLIMIT_NICE = _psutil_linux.RLIMIT_NICE
93        except AttributeError:
94            pass
95        try:
96            RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO
97        except AttributeError:
98            pass
99        try:
100            RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME
101        except AttributeError:
102            pass
103        try:
104            RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING
105        except AttributeError:
106            pass
107        del _psutil_linux
108
109elif sys.platform.startswith("win32"):
110    from . import _pswindows as _psplatform
111    from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS,  # NOQA
112                                  BELOW_NORMAL_PRIORITY_CLASS,
113                                  HIGH_PRIORITY_CLASS,
114                                  IDLE_PRIORITY_CLASS,
115                                  NORMAL_PRIORITY_CLASS,
116                                  REALTIME_PRIORITY_CLASS)
117    from ._pswindows import CONN_DELETE_TCB  # NOQA
118
119elif sys.platform.startswith("darwin"):
120    from . import _psosx as _psplatform
121
122elif sys.platform.startswith("freebsd"):
123    from . import _psbsd as _psplatform
124
125elif sys.platform.startswith("sunos"):
126    from . import _pssunos as _psplatform
127    from ._pssunos import (CONN_IDLE,  # NOQA
128                           CONN_BOUND)
129
130else:  # pragma: no cover
131    raise NotImplementedError('platform %s is not supported' % sys.platform)
132
133
134__all__ = [
135    # exceptions
136    "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied",
137    "TimeoutExpired",
138    # constants
139    "version_info", "__version__",
140    "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
141    "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
142    "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED",
143    "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1",
144    "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
145    "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE",
146    "AF_LINK",
147    "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN",
148    # classes
149    "Process", "Popen",
150    # functions
151    "pid_exists", "pids", "process_iter", "wait_procs",             # proc
152    "virtual_memory", "swap_memory",                                # memory
153    "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count",   # cpu
154    "net_io_counters", "net_connections", "net_if_addrs",           # network
155    "net_if_stats",
156    "disk_io_counters", "disk_partitions", "disk_usage",            # disk
157    "users", "boot_time",                                           # others
158]
159__all__.extend(_psplatform.__extra__all__)
160__author__ = "Giampaolo Rodola'"
161__version__ = "3.1.1"
162version_info = tuple([int(num) for num in __version__.split('.')])
163AF_LINK = _psplatform.AF_LINK
164_TOTAL_PHYMEM = None
165_POSIX = os.name == 'posix'
166_WINDOWS = os.name == 'nt'
167_timer = getattr(time, 'monotonic', time.time)
168
169
170# Sanity check in case the user messed up with psutil installation
171# or did something weird with sys.path. In this case we might end
172# up importing a python module using a C extension module which
173# was compiled for a different version of psutil.
174# We want to prevent that by failing sooner rather than later.
175# See: https://github.com/giampaolo/psutil/issues/564
176if (int(__version__.replace('.', '')) !=
177        getattr(_psplatform.cext, 'version', None)):
178    msg = "version conflict: %r C extension module was built for another " \
179          "version of psutil (different than %s)" % (_psplatform.cext.__file__,
180                                                     __version__)
181    raise ImportError(msg)
182
183
184# =====================================================================
185# --- exceptions
186# =====================================================================
187
188class Error(Exception):
189    """Base exception class. All other psutil exceptions inherit
190    from this one.
191    """
192
193    def __init__(self, msg=""):
194        self.msg = msg
195
196    def __repr__(self):
197        ret = "%s.%s %s" % (self.__class__.__module__,
198                            self.__class__.__name__, self.msg)
199        return ret.strip()
200
201    __str__ = __repr__
202
203
204class NoSuchProcess(Error):
205    """Exception raised when a process with a certain PID doesn't
206    or no longer exists.
207    """
208
209    def __init__(self, pid, name=None, msg=None):
210        Error.__init__(self, msg)
211        self.pid = pid
212        self.name = name
213        self.msg = msg
214        if msg is None:
215            if name:
216                details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
217            else:
218                details = "(pid=%s)" % self.pid
219            self.msg = "process no longer exists " + details
220
221
222class ZombieProcess(NoSuchProcess):
223    """Exception raised when querying a zombie process. This is
224    raised on OSX, BSD and Solaris only, and not always: depending
225    on the query the OS may be able to succeed anyway.
226    On Linux all zombie processes are querable (hence this is never
227    raised). Windows doesn't have zombie processes.
228    """
229
230    def __init__(self, pid, name=None, ppid=None, msg=None):
231        Error.__init__(self, msg)
232        self.pid = pid
233        self.ppid = ppid
234        self.name = name
235        self.msg = msg
236        if msg is None:
237            if name and ppid:
238                details = "(pid=%s, name=%s, ppid=%s)" % (
239                    self.pid, repr(self.name), self.ppid)
240            elif name:
241                details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
242            else:
243                details = "(pid=%s)" % self.pid
244            self.msg = "process still exists but it's a zombie " + details
245
246
247class AccessDenied(Error):
248    """Exception raised when permission to perform an action is denied."""
249
250    def __init__(self, pid=None, name=None, msg=None):
251        Error.__init__(self, msg)
252        self.pid = pid
253        self.name = name
254        self.msg = msg
255        if msg is None:
256            if (pid is not None) and (name is not None):
257                self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
258            elif (pid is not None):
259                self.msg = "(pid=%s)" % self.pid
260            else:
261                self.msg = ""
262
263
264class TimeoutExpired(Error):
265    """Raised on Process.wait(timeout) if timeout expires and process
266    is still alive.
267    """
268
269    def __init__(self, seconds, pid=None, name=None):
270        Error.__init__(self, "timeout after %s seconds" % seconds)
271        self.seconds = seconds
272        self.pid = pid
273        self.name = name
274        if (pid is not None) and (name is not None):
275            self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
276        elif (pid is not None):
277            self.msg += " (pid=%s)" % self.pid
278
279
280# push exception classes into platform specific module namespace
281_psplatform.NoSuchProcess = NoSuchProcess
282_psplatform.ZombieProcess = ZombieProcess
283_psplatform.AccessDenied = AccessDenied
284_psplatform.TimeoutExpired = TimeoutExpired
285
286
287# =====================================================================
288# --- Process class
289# =====================================================================
290
291
292def _assert_pid_not_reused(fun):
293    """Decorator which raises NoSuchProcess in case a process is no
294    longer running or its PID has been reused.
295    """
296    @functools.wraps(fun)
297    def wrapper(self, *args, **kwargs):
298        if not self.is_running():
299            raise NoSuchProcess(self.pid, self._name)
300        return fun(self, *args, **kwargs)
301    return wrapper
302
303
304class Process(object):
305    """Represents an OS process with the given PID.
306    If PID is omitted current process PID (os.getpid()) is used.
307    Raise NoSuchProcess if PID does not exist.
308
309    Note that most of the methods of this class do not make sure
310    the PID of the process being queried has been reused over time.
311    That means you might end up retrieving an information referring
312    to another process in case the original one this instance
313    refers to is gone in the meantime.
314
315    The only exceptions for which process identity is pre-emptively
316    checked and guaranteed are:
317
318     - parent()
319     - children()
320     - nice() (set)
321     - ionice() (set)
322     - rlimit() (set)
323     - cpu_affinity (set)
324     - suspend()
325     - resume()
326     - send_signal()
327     - terminate()
328     - kill()
329
330    To prevent this problem for all other methods you can:
331      - use is_running() before querying the process
332      - if you're continuously iterating over a set of Process
333        instances use process_iter() which pre-emptively checks
334        process identity for every yielded instance
335    """
336
337    def __init__(self, pid=None):
338        self._init(pid)
339
340    def _init(self, pid, _ignore_nsp=False):
341        if pid is None:
342            pid = os.getpid()
343        else:
344            if not _PY3 and not isinstance(pid, (int, long)):
345                raise TypeError('pid must be an integer (got %r)' % pid)
346            if pid < 0:
347                raise ValueError('pid must be a positive integer (got %s)'
348                                 % pid)
349        self._pid = pid
350        self._name = None
351        self._exe = None
352        self._create_time = None
353        self._gone = False
354        self._hash = None
355        # used for caching on Windows only (on POSIX ppid may change)
356        self._ppid = None
357        # platform-specific modules define an _psplatform.Process
358        # implementation class
359        self._proc = _psplatform.Process(pid)
360        self._last_sys_cpu_times = None
361        self._last_proc_cpu_times = None
362        # cache creation time for later use in is_running() method
363        try:
364            self.create_time()
365        except AccessDenied:
366            # we should never get here as AFAIK we're able to get
367            # process creation time on all platforms even as a
368            # limited user
369            pass
370        except ZombieProcess:
371            # Let's consider a zombie process as legitimate as
372            # tehcnically it's still alive (it can be queried,
373            # although not always, and it's returned by pids()).
374            pass
375        except NoSuchProcess:
376            if not _ignore_nsp:
377                msg = 'no process found with pid %s' % pid
378                raise NoSuchProcess(pid, None, msg)
379            else:
380                self._gone = True
381        # This pair is supposed to indentify a Process instance
382        # univocally over time (the PID alone is not enough as
383        # it might refer to a process whose PID has been reused).
384        # This will be used later in __eq__() and is_running().
385        self._ident = (self.pid, self._create_time)
386
387    def __str__(self):
388        try:
389            pid = self.pid
390            name = repr(self.name())
391        except ZombieProcess:
392            details = "(pid=%s (zombie))" % self.pid
393        except NoSuchProcess:
394            details = "(pid=%s (terminated))" % self.pid
395        except AccessDenied:
396            details = "(pid=%s)" % (self.pid)
397        else:
398            details = "(pid=%s, name=%s)" % (pid, name)
399        return "%s.%s%s" % (self.__class__.__module__,
400                            self.__class__.__name__, details)
401
402    def __repr__(self):
403        return "<%s at %s>" % (self.__str__(), id(self))
404
405    def __eq__(self, other):
406        # Test for equality with another Process object based
407        # on PID and creation time.
408        if not isinstance(other, Process):
409            return NotImplemented
410        return self._ident == other._ident
411
412    def __ne__(self, other):
413        return not self == other
414
415    def __hash__(self):
416        if self._hash is None:
417            self._hash = hash(self._ident)
418        return self._hash
419
420    # --- utility methods
421
422    def as_dict(self, attrs=None, ad_value=None):
423        """Utility method returning process information as a
424        hashable dictionary.
425
426        If 'attrs' is specified it must be a list of strings
427        reflecting available Process class' attribute names
428        (e.g. ['cpu_times', 'name']) else all public (read
429        only) attributes are assumed.
430
431        'ad_value' is the value which gets assigned in case
432        AccessDenied or ZombieProcess exception is raised when
433        retrieving that particular process information.
434        """
435        excluded_names = set(
436            ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
437             'is_running', 'as_dict', 'parent', 'children', 'rlimit'])
438        retdict = dict()
439        ls = set(attrs or [x for x in dir(self)])
440        for name in ls:
441            if name.startswith('_'):
442                continue
443            if name in excluded_names:
444                continue
445            try:
446                attr = getattr(self, name)
447                if callable(attr):
448                    ret = attr()
449                else:
450                    ret = attr
451            except (AccessDenied, ZombieProcess):
452                ret = ad_value
453            except NotImplementedError:
454                # in case of not implemented functionality (may happen
455                # on old or exotic systems) we want to crash only if
456                # the user explicitly asked for that particular attr
457                if attrs:
458                    raise
459                continue
460            retdict[name] = ret
461        return retdict
462
463    def parent(self):
464        """Return the parent process as a Process object pre-emptively
465        checking whether PID has been reused.
466        If no parent is known return None.
467        """
468        ppid = self.ppid()
469        if ppid is not None:
470            ctime = self.create_time()
471            try:
472                parent = Process(ppid)
473                if parent.create_time() <= ctime:
474                    return parent
475                # ...else ppid has been reused by another process
476            except NoSuchProcess:
477                pass
478
479    def is_running(self):
480        """Return whether this process is running.
481        It also checks if PID has been reused by another process in
482        which case return False.
483        """
484        if self._gone:
485            return False
486        try:
487            # Checking if PID is alive is not enough as the PID might
488            # have been reused by another process: we also want to
489            # check process identity.
490            # Process identity / uniqueness over time is greanted by
491            # (PID + creation time) and that is verified in __eq__.
492            return self == Process(self.pid)
493        except NoSuchProcess:
494            self._gone = True
495            return False
496
497    # --- actual API
498
499    @property
500    def pid(self):
501        """The process PID."""
502        return self._pid
503
504    def ppid(self):
505        """The process parent PID.
506        On Windows the return value is cached after first call.
507        """
508        # On POSIX we don't want to cache the ppid as it may unexpectedly
509        # change to 1 (init) in case this process turns into a zombie:
510        # https://github.com/giampaolo/psutil/issues/321
511        # http://stackoverflow.com/questions/356722/
512
513        # XXX should we check creation time here rather than in
514        # Process.parent()?
515        if _POSIX:
516            return self._proc.ppid()
517        else:
518            self._ppid = self._ppid or self._proc.ppid()
519            return self._ppid
520
521    def name(self):
522        """The process name. The return value is cached after first call."""
523        if self._name is None:
524            name = self._proc.name()
525            if _POSIX and len(name) >= 15:
526                # On UNIX the name gets truncated to the first 15 characters.
527                # If it matches the first part of the cmdline we return that
528                # one instead because it's usually more explicative.
529                # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon".
530                try:
531                    cmdline = self.cmdline()
532                except AccessDenied:
533                    pass
534                else:
535                    if cmdline:
536                        extended_name = os.path.basename(cmdline[0])
537                        if extended_name.startswith(name):
538                            name = extended_name
539            self._proc._name = name
540            self._name = name
541        return self._name
542
543    def exe(self):
544        """The process executable as an absolute path.
545        May also be an empty string.
546        The return value is cached after first call.
547        """
548        def guess_it(fallback):
549            # try to guess exe from cmdline[0] in absence of a native
550            # exe representation
551            cmdline = self.cmdline()
552            if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'):
553                exe = cmdline[0]  # the possible exe
554                # Attempt to guess only in case of an absolute path.
555                # It is not safe otherwise as the process might have
556                # changed cwd.
557                if (os.path.isabs(exe) and
558                        os.path.isfile(exe) and
559                        os.access(exe, os.X_OK)):
560                    return exe
561            if isinstance(fallback, AccessDenied):
562                raise fallback
563            return fallback
564
565        if self._exe is None:
566            try:
567                exe = self._proc.exe()
568            except AccessDenied as err:
569                return guess_it(fallback=err)
570            else:
571                if not exe:
572                    # underlying implementation can legitimately return an
573                    # empty string; if that's the case we don't want to
574                    # raise AD while guessing from the cmdline
575                    try:
576                        exe = guess_it(fallback=exe)
577                    except AccessDenied:
578                        pass
579                self._exe = exe
580        return self._exe
581
582    def cmdline(self):
583        """The command line this process has been called with."""
584        return self._proc.cmdline()
585
586    def status(self):
587        """The process current status as a STATUS_* constant."""
588        try:
589            return self._proc.status()
590        except ZombieProcess:
591            return STATUS_ZOMBIE
592
593    def username(self):
594        """The name of the user that owns the process.
595        On UNIX this is calculated by using *real* process uid.
596        """
597        if _POSIX:
598            if pwd is None:
599                # might happen if python was installed from sources
600                raise ImportError(
601                    "requires pwd module shipped with standard python")
602            real_uid = self.uids().real
603            try:
604                return pwd.getpwuid(real_uid).pw_name
605            except KeyError:
606                # the uid can't be resolved by the system
607                return str(real_uid)
608        else:
609            return self._proc.username()
610
611    def create_time(self):
612        """The process creation time as a floating point number
613        expressed in seconds since the epoch, in UTC.
614        The return value is cached after first call.
615        """
616        if self._create_time is None:
617            self._create_time = self._proc.create_time()
618        return self._create_time
619
620    def cwd(self):
621        """Process current working directory as an absolute path."""
622        return self._proc.cwd()
623
624    def nice(self, value=None):
625        """Get or set process niceness (priority)."""
626        if value is None:
627            return self._proc.nice_get()
628        else:
629            if not self.is_running():
630                raise NoSuchProcess(self.pid, self._name)
631            self._proc.nice_set(value)
632
633    if _POSIX:
634
635        def uids(self):
636            """Return process UIDs as a (real, effective, saved)
637            namedtuple.
638            """
639            return self._proc.uids()
640
641        def gids(self):
642            """Return process GIDs as a (real, effective, saved)
643            namedtuple.
644            """
645            return self._proc.gids()
646
647        def terminal(self):
648            """The terminal associated with this process, if any,
649            else None.
650            """
651            return self._proc.terminal()
652
653        def num_fds(self):
654            """Return the number of file descriptors opened by this
655            process (POSIX only).
656            """
657            return self._proc.num_fds()
658
659    # Linux, BSD and Windows only
660    if hasattr(_psplatform.Process, "io_counters"):
661
662        def io_counters(self):
663            """Return process I/O statistics as a
664            (read_count, write_count, read_bytes, write_bytes)
665            namedtuple.
666            Those are the number of read/write calls performed and the
667            amount of bytes read and written by the process.
668            """
669            return self._proc.io_counters()
670
671    # Linux and Windows >= Vista only
672    if hasattr(_psplatform.Process, "ionice_get"):
673
674        def ionice(self, ioclass=None, value=None):
675            """Get or set process I/O niceness (priority).
676
677            On Linux 'ioclass' is one of the IOPRIO_CLASS_* constants.
678            'value' is a number which goes from 0 to 7. The higher the
679            value, the lower the I/O priority of the process.
680
681            On Windows only 'ioclass' is used and it can be set to 2
682            (normal), 1 (low) or 0 (very low).
683
684            Available on Linux and Windows > Vista only.
685            """
686            if ioclass is None:
687                if value is not None:
688                    raise ValueError("'ioclass' argument must be specified")
689                return self._proc.ionice_get()
690            else:
691                return self._proc.ionice_set(ioclass, value)
692
693    # Linux only
694    if hasattr(_psplatform.Process, "rlimit"):
695
696        def rlimit(self, resource, limits=None):
697            """Get or set process resource limits as a (soft, hard)
698            tuple.
699
700            'resource' is one of the RLIMIT_* constants.
701            'limits' is supposed to be a (soft, hard)  tuple.
702
703            See "man prlimit" for further info.
704            Available on Linux only.
705            """
706            if limits is None:
707                return self._proc.rlimit(resource)
708            else:
709                return self._proc.rlimit(resource, limits)
710
711    # Windows, Linux and BSD only
712    if hasattr(_psplatform.Process, "cpu_affinity_get"):
713
714        def cpu_affinity(self, cpus=None):
715            """Get or set process CPU affinity.
716            If specified 'cpus' must be a list of CPUs for which you
717            want to set the affinity (e.g. [0, 1]).
718            (Windows, Linux and BSD only).
719            """
720            # Automatically remove duplicates both on get and
721            # set (for get it's not really necessary, it's
722            # just for extra safety).
723            if cpus is None:
724                return list(set(self._proc.cpu_affinity_get()))
725            else:
726                self._proc.cpu_affinity_set(list(set(cpus)))
727
728    if _WINDOWS:
729
730        def num_handles(self):
731            """Return the number of handles opened by this process
732            (Windows only).
733            """
734            return self._proc.num_handles()
735
736    def num_ctx_switches(self):
737        """Return the number of voluntary and involuntary context
738        switches performed by this process.
739        """
740        return self._proc.num_ctx_switches()
741
742    def num_threads(self):
743        """Return the number of threads used by this process."""
744        return self._proc.num_threads()
745
746    def threads(self):
747        """Return threads opened by process as a list of
748        (id, user_time, system_time) namedtuples representing
749        thread id and thread CPU times (user/system).
750        """
751        return self._proc.threads()
752
753    @_assert_pid_not_reused
754    def children(self, recursive=False):
755        """Return the children of this process as a list of Process
756        instances, pre-emptively checking whether PID has been reused.
757        If recursive is True return all the parent descendants.
758
759        Example (A == this process):
760
761         A ─┐
762763            ├─ B (child) ─┐
764            │             └─ X (grandchild) ─┐
765            │                                └─ Y (great grandchild)
766            ├─ C (child)
767            └─ D (child)
768
769        >>> import psutil
770        >>> p = psutil.Process()
771        >>> p.children()
772        B, C, D
773        >>> p.children(recursive=True)
774        B, X, Y, C, D
775
776        Note that in the example above if process X disappears
777        process Y won't be listed as the reference to process A
778        is lost.
779        """
780        if hasattr(_psplatform, 'ppid_map'):
781            # Windows only: obtain a {pid:ppid, ...} dict for all running
782            # processes in one shot (faster).
783            ppid_map = _psplatform.ppid_map()
784        else:
785            ppid_map = None
786
787        ret = []
788        if not recursive:
789            if ppid_map is None:
790                # 'slow' version, common to all platforms except Windows
791                for p in process_iter():
792                    try:
793                        if p.ppid() == self.pid:
794                            # if child happens to be older than its parent
795                            # (self) it means child's PID has been reused
796                            if self.create_time() <= p.create_time():
797                                ret.append(p)
798                    except (NoSuchProcess, ZombieProcess):
799                        pass
800            else:
801                # Windows only (faster)
802                for pid, ppid in ppid_map.items():
803                    if ppid == self.pid:
804                        try:
805                            child = Process(pid)
806                            # if child happens to be older than its parent
807                            # (self) it means child's PID has been reused
808                            if self.create_time() <= child.create_time():
809                                ret.append(child)
810                        except (NoSuchProcess, ZombieProcess):
811                            pass
812        else:
813            # construct a dict where 'values' are all the processes
814            # having 'key' as their parent
815            table = collections.defaultdict(list)
816            if ppid_map is None:
817                for p in process_iter():
818                    try:
819                        table[p.ppid()].append(p)
820                    except (NoSuchProcess, ZombieProcess):
821                        pass
822            else:
823                for pid, ppid in ppid_map.items():
824                    try:
825                        p = Process(pid)
826                        table[ppid].append(p)
827                    except (NoSuchProcess, ZombieProcess):
828                        pass
829            # At this point we have a mapping table where table[self.pid]
830            # are the current process' children.
831            # Below, we look for all descendants recursively, similarly
832            # to a recursive function call.
833            checkpids = [self.pid]
834            for pid in checkpids:
835                for child in table[pid]:
836                    try:
837                        # if child happens to be older than its parent
838                        # (self) it means child's PID has been reused
839                        intime = self.create_time() <= child.create_time()
840                    except (NoSuchProcess, ZombieProcess):
841                        pass
842                    else:
843                        if intime:
844                            ret.append(child)
845                            if child.pid not in checkpids:
846                                checkpids.append(child.pid)
847        return ret
848
849    def cpu_percent(self, interval=None):
850        """Return a float representing the current process CPU
851        utilization as a percentage.
852
853        When interval is 0.0 or None (default) compares process times
854        to system CPU times elapsed since last call, returning
855        immediately (non-blocking). That means that the first time
856        this is called it will return a meaningful 0.0 value.
857
858        When interval is > 0.0 compares process times to system CPU
859        times elapsed before and after the interval (blocking).
860
861        In this case is recommended for accuracy that this function
862        be called with at least 0.1 seconds between calls.
863
864        Examples:
865
866          >>> import psutil
867          >>> p = psutil.Process(os.getpid())
868          >>> # blocking
869          >>> p.cpu_percent(interval=1)
870          2.0
871          >>> # non-blocking (percentage since last call)
872          >>> p.cpu_percent(interval=None)
873          2.9
874          >>>
875        """
876        blocking = interval is not None and interval > 0.0
877        num_cpus = cpu_count()
878        if _POSIX:
879            def timer():
880                return _timer() * num_cpus
881        else:
882            def timer():
883                return sum(cpu_times())
884        if blocking:
885            st1 = timer()
886            pt1 = self._proc.cpu_times()
887            time.sleep(interval)
888            st2 = timer()
889            pt2 = self._proc.cpu_times()
890        else:
891            st1 = self._last_sys_cpu_times
892            pt1 = self._last_proc_cpu_times
893            st2 = timer()
894            pt2 = self._proc.cpu_times()
895            if st1 is None or pt1 is None:
896                self._last_sys_cpu_times = st2
897                self._last_proc_cpu_times = pt2
898                return 0.0
899
900        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
901        delta_time = st2 - st1
902        # reset values for next call in case of interval == None
903        self._last_sys_cpu_times = st2
904        self._last_proc_cpu_times = pt2
905
906        try:
907            # The utilization split between all CPUs.
908            # Note: a percentage > 100 is legitimate as it can result
909            # from a process with multiple threads running on different
910            # CPU cores, see:
911            # http://stackoverflow.com/questions/1032357
912            # https://github.com/giampaolo/psutil/issues/474
913            overall_percent = ((delta_proc / delta_time) * 100) * num_cpus
914        except ZeroDivisionError:
915            # interval was too low
916            return 0.0
917        else:
918            return round(overall_percent, 1)
919
920    def cpu_times(self):
921        """Return a (user, system) namedtuple representing  the
922        accumulated process time, in seconds.
923        This is the same as os.times() but per-process.
924        """
925        return self._proc.cpu_times()
926
927    def memory_info(self):
928        """Return a tuple representing RSS (Resident Set Size) and VMS
929        (Virtual Memory Size) in bytes.
930
931        On UNIX RSS and VMS are the same values shown by 'ps'.
932
933        On Windows RSS and VMS refer to "Mem Usage" and "VM Size"
934        columns of taskmgr.exe.
935        """
936        return self._proc.memory_info()
937
938    def memory_info_ex(self):
939        """Return a namedtuple with variable fields depending on the
940        platform representing extended memory information about
941        this process. All numbers are expressed in bytes.
942        """
943        return self._proc.memory_info_ex()
944
945    def memory_percent(self):
946        """Compare physical system memory to process resident memory
947        (RSS) and calculate process memory utilization as a percentage.
948        """
949        rss = self._proc.memory_info()[0]
950        # use cached value if available
951        total_phymem = _TOTAL_PHYMEM or virtual_memory().total
952        try:
953            return (rss / float(total_phymem)) * 100
954        except ZeroDivisionError:
955            return 0.0
956
957    def memory_maps(self, grouped=True):
958        """Return process' mapped memory regions as a list of namedtuples
959        whose fields are variable depending on the platform.
960
961        If 'grouped' is True the mapped regions with the same 'path'
962        are grouped together and the different memory fields are summed.
963
964        If 'grouped' is False every mapped region is shown as a single
965        entity and the namedtuple will also include the mapped region's
966        address space ('addr') and permission set ('perms').
967        """
968        it = self._proc.memory_maps()
969        if grouped:
970            d = {}
971            for tupl in it:
972                path = tupl[2]
973                nums = tupl[3:]
974                try:
975                    d[path] = map(lambda x, y: x + y, d[path], nums)
976                except KeyError:
977                    d[path] = nums
978            nt = _psplatform.pmmap_grouped
979            return [nt(path, *d[path]) for path in d]  # NOQA
980        else:
981            nt = _psplatform.pmmap_ext
982            return [nt(*x) for x in it]
983
984    def open_files(self):
985        """Return files opened by process as a list of
986        (path, fd) namedtuples including the absolute file name
987        and file descriptor number.
988        """
989        return self._proc.open_files()
990
991    def connections(self, kind='inet'):
992        """Return connections opened by process as a list of
993        (fd, family, type, laddr, raddr, status) namedtuples.
994        The 'kind' parameter filters for connections that match the
995        following criteria:
996
997        Kind Value      Connections using
998        inet            IPv4 and IPv6
999        inet4           IPv4
1000        inet6           IPv6
1001        tcp             TCP
1002        tcp4            TCP over IPv4
1003        tcp6            TCP over IPv6
1004        udp             UDP
1005        udp4            UDP over IPv4
1006        udp6            UDP over IPv6
1007        unix            UNIX socket (both UDP and TCP protocols)
1008        all             the sum of all the possible families and protocols
1009        """
1010        return self._proc.connections(kind)
1011
1012    if _POSIX:
1013        def _send_signal(self, sig):
1014            if self.pid == 0:
1015                # see "man 2 kill"
1016                raise ValueError(
1017                    "preventing sending signal to process with PID 0 as it "
1018                    "would affect every process in the process group of the "
1019                    "calling process (os.getpid()) instead of PID 0")
1020            try:
1021                os.kill(self.pid, sig)
1022            except OSError as err:
1023                if err.errno == errno.ESRCH:
1024                    self._gone = True
1025                    raise NoSuchProcess(self.pid, self._name)
1026                if err.errno == errno.EPERM:
1027                    raise AccessDenied(self.pid, self._name)
1028                raise
1029
1030    @_assert_pid_not_reused
1031    def send_signal(self, sig):
1032        """Send a signal to process pre-emptively checking whether
1033        PID has been reused (see signal module constants) .
1034        On Windows only SIGTERM is valid and is treated as an alias
1035        for kill().
1036        """
1037        if _POSIX:
1038            self._send_signal(sig)
1039        else:
1040            if sig == signal.SIGTERM:
1041                self._proc.kill()
1042            else:
1043                raise ValueError("only SIGTERM is supported on Windows")
1044
1045    @_assert_pid_not_reused
1046    def suspend(self):
1047        """Suspend process execution with SIGSTOP pre-emptively checking
1048        whether PID has been reused.
1049        On Windows this has the effect ot suspending all process threads.
1050        """
1051        if _POSIX:
1052            self._send_signal(signal.SIGSTOP)
1053        else:
1054            self._proc.suspend()
1055
1056    @_assert_pid_not_reused
1057    def resume(self):
1058        """Resume process execution with SIGCONT pre-emptively checking
1059        whether PID has been reused.
1060        On Windows this has the effect of resuming all process threads.
1061        """
1062        if _POSIX:
1063            self._send_signal(signal.SIGCONT)
1064        else:
1065            self._proc.resume()
1066
1067    @_assert_pid_not_reused
1068    def terminate(self):
1069        """Terminate the process with SIGTERM pre-emptively checking
1070        whether PID has been reused.
1071        On Windows this is an alias for kill().
1072        """
1073        if _POSIX:
1074            self._send_signal(signal.SIGTERM)
1075        else:
1076            self._proc.kill()
1077
1078    @_assert_pid_not_reused
1079    def kill(self):
1080        """Kill the current process with SIGKILL pre-emptively checking
1081        whether PID has been reused.
1082        """
1083        if _POSIX:
1084            self._send_signal(signal.SIGKILL)
1085        else:
1086            self._proc.kill()
1087
1088    def wait(self, timeout=None):
1089        """Wait for process to terminate and, if process is a children
1090        of os.getpid(), also return its exit code, else None.
1091
1092        If the process is already terminated immediately return None
1093        instead of raising NoSuchProcess.
1094
1095        If timeout (in seconds) is specified and process is still alive
1096        raise TimeoutExpired.
1097
1098        To wait for multiple Process(es) use psutil.wait_procs().
1099        """
1100        if timeout is not None and not timeout >= 0:
1101            raise ValueError("timeout must be a positive integer")
1102        return self._proc.wait(timeout)
1103
1104
1105# =====================================================================
1106# --- Popen class
1107# =====================================================================
1108
1109
1110class Popen(Process):
1111    """A more convenient interface to stdlib subprocess module.
1112    It starts a sub process and deals with it exactly as when using
1113    subprocess.Popen class but in addition also provides all the
1114    properties and methods of psutil.Process class as a unified
1115    interface:
1116
1117      >>> import psutil
1118      >>> from subprocess import PIPE
1119      >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE)
1120      >>> p.name()
1121      'python'
1122      >>> p.uids()
1123      user(real=1000, effective=1000, saved=1000)
1124      >>> p.username()
1125      'giampaolo'
1126      >>> p.communicate()
1127      ('hi\n', None)
1128      >>> p.terminate()
1129      >>> p.wait(timeout=2)
1130      0
1131      >>>
1132
1133    For method names common to both classes such as kill(), terminate()
1134    and wait(), psutil.Process implementation takes precedence.
1135
1136    Unlike subprocess.Popen this class pre-emptively checks wheter PID
1137    has been reused on send_signal(), terminate() and kill() so that
1138    you don't accidentally terminate another process, fixing
1139    http://bugs.python.org/issue6973.
1140
1141    For a complete documentation refer to:
1142    http://docs.python.org/library/subprocess.html
1143    """
1144
1145    def __init__(self, *args, **kwargs):
1146        # Explicitly avoid to raise NoSuchProcess in case the process
1147        # spawned by subprocess.Popen terminates too quickly, see:
1148        # https://github.com/giampaolo/psutil/issues/193
1149        self.__subproc = subprocess.Popen(*args, **kwargs)
1150        self._init(self.__subproc.pid, _ignore_nsp=True)
1151
1152    def __dir__(self):
1153        return sorted(set(dir(Popen) + dir(subprocess.Popen)))
1154
1155    def __getattribute__(self, name):
1156        try:
1157            return object.__getattribute__(self, name)
1158        except AttributeError:
1159            try:
1160                return object.__getattribute__(self.__subproc, name)
1161            except AttributeError:
1162                raise AttributeError("%s instance has no attribute '%s'"
1163                                     % (self.__class__.__name__, name))
1164
1165    def wait(self, timeout=None):
1166        if self.__subproc.returncode is not None:
1167            return self.__subproc.returncode
1168        ret = super(Popen, self).wait(timeout)
1169        self.__subproc.returncode = ret
1170        return ret
1171
1172
1173# =====================================================================
1174# --- system processes related functions
1175# =====================================================================
1176
1177
1178def pids():
1179    """Return a list of current running PIDs."""
1180    return _psplatform.pids()
1181
1182
1183def pid_exists(pid):
1184    """Return True if given PID exists in the current process list.
1185    This is faster than doing "pid in psutil.pids()" and
1186    should be preferred.
1187    """
1188    if pid < 0:
1189        return False
1190    elif pid == 0 and _POSIX:
1191        # On POSIX we use os.kill() to determine PID existence.
1192        # According to "man 2 kill" PID 0 has a special meaning
1193        # though: it refers to <<every process in the process
1194        # group of the calling process>> and that is not we want
1195        # to do here.
1196        return pid in pids()
1197    else:
1198        return _psplatform.pid_exists(pid)
1199
1200
1201_pmap = {}
1202
1203
1204def process_iter():
1205    """Return a generator yielding a Process instance for all
1206    running processes.
1207
1208    Every new Process instance is only created once and then cached
1209    into an internal table which is updated every time this is used.
1210
1211    Cached Process instances are checked for identity so that you're
1212    safe in case a PID has been reused by another process, in which
1213    case the cached instance is updated.
1214
1215    The sorting order in which processes are yielded is based on
1216    their PIDs.
1217    """
1218    def add(pid):
1219        proc = Process(pid)
1220        _pmap[proc.pid] = proc
1221        return proc
1222
1223    def remove(pid):
1224        _pmap.pop(pid, None)
1225
1226    a = set(pids())
1227    b = set(_pmap.keys())
1228    new_pids = a - b
1229    gone_pids = b - a
1230
1231    for pid in gone_pids:
1232        remove(pid)
1233    for pid, proc in sorted(list(_pmap.items()) +
1234                            list(dict.fromkeys(new_pids).items())):
1235        try:
1236            if proc is None:  # new process
1237                yield add(pid)
1238            else:
1239                # use is_running() to check whether PID has been reused by
1240                # another process in which case yield a new Process instance
1241                if proc.is_running():
1242                    yield proc
1243                else:
1244                    yield add(pid)
1245        except NoSuchProcess:
1246            remove(pid)
1247        except AccessDenied:
1248            # Process creation time can't be determined hence there's
1249            # no way to tell whether the pid of the cached process
1250            # has been reused. Just return the cached version.
1251            yield proc
1252
1253
1254def wait_procs(procs, timeout=None, callback=None):
1255    """Convenience function which waits for a list of processes to
1256    terminate.
1257
1258    Return a (gone, alive) tuple indicating which processes
1259    are gone and which ones are still alive.
1260
1261    The gone ones will have a new 'returncode' attribute indicating
1262    process exit status (may be None).
1263
1264    'callback' is a function which gets called every time a process
1265    terminates (a Process instance is passed as callback argument).
1266
1267    Function will return as soon as all processes terminate or when
1268    timeout occurs.
1269
1270    Typical use case is:
1271
1272     - send SIGTERM to a list of processes
1273     - give them some time to terminate
1274     - send SIGKILL to those ones which are still alive
1275
1276    Example:
1277
1278    >>> def on_terminate(proc):
1279    ...     print("process {} terminated".format(proc))
1280    ...
1281    >>> for p in procs:
1282    ...    p.terminate()
1283    ...
1284    >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate)
1285    >>> for p in alive:
1286    ...     p.kill()
1287    """
1288    def check_gone(proc, timeout):
1289        try:
1290            returncode = proc.wait(timeout=timeout)
1291        except TimeoutExpired:
1292            pass
1293        else:
1294            if returncode is not None or not proc.is_running():
1295                proc.returncode = returncode
1296                gone.add(proc)
1297                if callback is not None:
1298                    callback(proc)
1299
1300    if timeout is not None and not timeout >= 0:
1301        msg = "timeout must be a positive integer, got %s" % timeout
1302        raise ValueError(msg)
1303    gone = set()
1304    alive = set(procs)
1305    if callback is not None and not callable(callback):
1306        raise TypeError("callback %r is not a callable" % callable)
1307    if timeout is not None:
1308        deadline = _timer() + timeout
1309
1310    while alive:
1311        if timeout is not None and timeout <= 0:
1312            break
1313        for proc in alive:
1314            # Make sure that every complete iteration (all processes)
1315            # will last max 1 sec.
1316            # We do this because we don't want to wait too long on a
1317            # single process: in case it terminates too late other
1318            # processes may disappear in the meantime and their PID
1319            # reused.
1320            max_timeout = 1.0 / len(alive)
1321            if timeout is not None:
1322                timeout = min((deadline - _timer()), max_timeout)
1323                if timeout <= 0:
1324                    break
1325                check_gone(proc, timeout)
1326            else:
1327                check_gone(proc, max_timeout)
1328        alive = alive - gone
1329
1330    if alive:
1331        # Last attempt over processes survived so far.
1332        # timeout == 0 won't make this function wait any further.
1333        for proc in alive:
1334            check_gone(proc, 0)
1335        alive = alive - gone
1336
1337    return (list(gone), list(alive))
1338
1339
1340# =====================================================================
1341# --- CPU related functions
1342# =====================================================================
1343
1344
1345@memoize
1346def cpu_count(logical=True):
1347    """Return the number of logical CPUs in the system (same as
1348    os.cpu_count() in Python 3.4).
1349
1350    If logical is False return the number of physical cores only
1351    (e.g. hyper thread CPUs are excluded).
1352
1353    Return None if undetermined.
1354
1355    The return value is cached after first call.
1356    If desired cache can be cleared like this:
1357
1358    >>> psutil.cpu_count.cache_clear()
1359    """
1360    if logical:
1361        return _psplatform.cpu_count_logical()
1362    else:
1363        return _psplatform.cpu_count_physical()
1364
1365
1366def cpu_times(percpu=False):
1367    """Return system-wide CPU times as a namedtuple.
1368    Every CPU time represents the seconds the CPU has spent in the given mode.
1369    The namedtuple's fields availability varies depending on the platform:
1370     - user
1371     - system
1372     - idle
1373     - nice (UNIX)
1374     - iowait (Linux)
1375     - irq (Linux, FreeBSD)
1376     - softirq (Linux)
1377     - steal (Linux >= 2.6.11)
1378     - guest (Linux >= 2.6.24)
1379     - guest_nice (Linux >= 3.2.0)
1380
1381    When percpu is True return a list of namedtuples for each CPU.
1382    First element of the list refers to first CPU, second element
1383    to second CPU and so on.
1384    The order of the list is consistent across calls.
1385    """
1386    if not percpu:
1387        return _psplatform.cpu_times()
1388    else:
1389        return _psplatform.per_cpu_times()
1390
1391
1392_last_cpu_times = cpu_times()
1393_last_per_cpu_times = cpu_times(percpu=True)
1394
1395
1396def cpu_percent(interval=None, percpu=False):
1397    """Return a float representing the current system-wide CPU
1398    utilization as a percentage.
1399
1400    When interval is > 0.0 compares system CPU times elapsed before
1401    and after the interval (blocking).
1402
1403    When interval is 0.0 or None compares system CPU times elapsed
1404    since last call or module import, returning immediately (non
1405    blocking). That means the first time this is called it will
1406    return a meaningless 0.0 value which you should ignore.
1407    In this case is recommended for accuracy that this function be
1408    called with at least 0.1 seconds between calls.
1409
1410    When percpu is True returns a list of floats representing the
1411    utilization as a percentage for each CPU.
1412    First element of the list refers to first CPU, second element
1413    to second CPU and so on.
1414    The order of the list is consistent across calls.
1415
1416    Examples:
1417
1418      >>> # blocking, system-wide
1419      >>> psutil.cpu_percent(interval=1)
1420      2.0
1421      >>>
1422      >>> # blocking, per-cpu
1423      >>> psutil.cpu_percent(interval=1, percpu=True)
1424      [2.0, 1.0]
1425      >>>
1426      >>> # non-blocking (percentage since last call)
1427      >>> psutil.cpu_percent(interval=None)
1428      2.9
1429      >>>
1430    """
1431    global _last_cpu_times
1432    global _last_per_cpu_times
1433    blocking = interval is not None and interval > 0.0
1434
1435    def calculate(t1, t2):
1436        t1_all = sum(t1)
1437        t1_busy = t1_all - t1.idle
1438
1439        t2_all = sum(t2)
1440        t2_busy = t2_all - t2.idle
1441
1442        # this usually indicates a float precision issue
1443        if t2_busy <= t1_busy:
1444            return 0.0
1445
1446        busy_delta = t2_busy - t1_busy
1447        all_delta = t2_all - t1_all
1448        busy_perc = (busy_delta / all_delta) * 100
1449        return round(busy_perc, 1)
1450
1451    # system-wide usage
1452    if not percpu:
1453        if blocking:
1454            t1 = cpu_times()
1455            time.sleep(interval)
1456        else:
1457            t1 = _last_cpu_times
1458        _last_cpu_times = cpu_times()
1459        return calculate(t1, _last_cpu_times)
1460    # per-cpu usage
1461    else:
1462        ret = []
1463        if blocking:
1464            tot1 = cpu_times(percpu=True)
1465            time.sleep(interval)
1466        else:
1467            tot1 = _last_per_cpu_times
1468        _last_per_cpu_times = cpu_times(percpu=True)
1469        for t1, t2 in zip(tot1, _last_per_cpu_times):
1470            ret.append(calculate(t1, t2))
1471        return ret
1472
1473
1474# Use separate global vars for cpu_times_percent() so that it's
1475# independent from cpu_percent() and they can both be used within
1476# the same program.
1477_last_cpu_times_2 = _last_cpu_times
1478_last_per_cpu_times_2 = _last_per_cpu_times
1479
1480
1481def cpu_times_percent(interval=None, percpu=False):
1482    """Same as cpu_percent() but provides utilization percentages
1483    for each specific CPU time as is returned by cpu_times().
1484    For instance, on Linux we'll get:
1485
1486      >>> cpu_times_percent()
1487      cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0,
1488                 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
1489      >>>
1490
1491    interval and percpu arguments have the same meaning as in
1492    cpu_percent().
1493    """
1494    global _last_cpu_times_2
1495    global _last_per_cpu_times_2
1496    blocking = interval is not None and interval > 0.0
1497
1498    def calculate(t1, t2):
1499        nums = []
1500        all_delta = sum(t2) - sum(t1)
1501        for field in t1._fields:
1502            field_delta = getattr(t2, field) - getattr(t1, field)
1503            try:
1504                field_perc = (100 * field_delta) / all_delta
1505            except ZeroDivisionError:
1506                field_perc = 0.0
1507            field_perc = round(field_perc, 1)
1508            # CPU times are always supposed to increase over time
1509            # or at least remain the same and that's because time
1510            # cannot go backwards.
1511            # Surprisingly sometimes this might not be the case (at
1512            # least on Windows and Linux), see:
1513            # https://github.com/giampaolo/psutil/issues/392
1514            # https://github.com/giampaolo/psutil/issues/645
1515            # I really don't know what to do about that except
1516            # forcing the value to 0 or 100.
1517            if field_perc > 100.0:
1518                field_perc = 100.0
1519            # `<=` because `-0.0 == 0.0` evaluates to True
1520            elif field_perc <= 0.0:
1521                field_perc = 0.0
1522            nums.append(field_perc)
1523        return _psplatform.scputimes(*nums)
1524
1525    # system-wide usage
1526    if not percpu:
1527        if blocking:
1528            t1 = cpu_times()
1529            time.sleep(interval)
1530        else:
1531            t1 = _last_cpu_times_2
1532        _last_cpu_times_2 = cpu_times()
1533        return calculate(t1, _last_cpu_times_2)
1534    # per-cpu usage
1535    else:
1536        ret = []
1537        if blocking:
1538            tot1 = cpu_times(percpu=True)
1539            time.sleep(interval)
1540        else:
1541            tot1 = _last_per_cpu_times_2
1542        _last_per_cpu_times_2 = cpu_times(percpu=True)
1543        for t1, t2 in zip(tot1, _last_per_cpu_times_2):
1544            ret.append(calculate(t1, t2))
1545        return ret
1546
1547
1548# =====================================================================
1549# --- system memory related functions
1550# =====================================================================
1551
1552
1553def virtual_memory():
1554    """Return statistics about system memory usage as a namedtuple
1555    including the following fields, expressed in bytes:
1556
1557     - total:
1558       total physical memory available.
1559
1560     - available:
1561       the actual amount of available memory that can be given
1562       instantly to processes that request more memory in bytes; this
1563       is calculated by summing different memory values depending on
1564       the platform (e.g. free + buffers + cached on Linux) and it is
1565       supposed to be used to monitor actual memory usage in a cross
1566       platform fashion.
1567
1568     - percent:
1569       the percentage usage calculated as (total - available) / total * 100
1570
1571     - used:
1572       memory used, calculated differently depending on the platform and
1573       designed for informational purposes only:
1574        OSX: active + inactive + wired
1575        BSD: active + wired + cached
1576        LINUX: total - free
1577
1578     - free:
1579       memory not being used at all (zeroed) that is readily available;
1580       note that this doesn't reflect the actual memory available
1581       (use 'available' instead)
1582
1583    Platform-specific fields:
1584
1585     - active (UNIX):
1586       memory currently in use or very recently used, and so it is in RAM.
1587
1588     - inactive (UNIX):
1589       memory that is marked as not used.
1590
1591     - buffers (BSD, Linux):
1592       cache for things like file system metadata.
1593
1594     - cached (BSD, OSX):
1595       cache for various things.
1596
1597     - wired (OSX, BSD):
1598       memory that is marked to always stay in RAM. It is never moved to disk.
1599
1600     - shared (BSD):
1601       memory that may be simultaneously accessed by multiple processes.
1602
1603    The sum of 'used' and 'available' does not necessarily equal total.
1604    On Windows 'available' and 'free' are the same.
1605    """
1606    global _TOTAL_PHYMEM
1607    ret = _psplatform.virtual_memory()
1608    # cached for later use in Process.memory_percent()
1609    _TOTAL_PHYMEM = ret.total
1610    return ret
1611
1612
1613def swap_memory():
1614    """Return system swap memory statistics as a namedtuple including
1615    the following fields:
1616
1617     - total:   total swap memory in bytes
1618     - used:    used swap memory in bytes
1619     - free:    free swap memory in bytes
1620     - percent: the percentage usage
1621     - sin:     no. of bytes the system has swapped in from disk (cumulative)
1622     - sout:    no. of bytes the system has swapped out from disk (cumulative)
1623
1624    'sin' and 'sout' on Windows are meaningless and always set to 0.
1625    """
1626    return _psplatform.swap_memory()
1627
1628
1629# =====================================================================
1630# --- disks/paritions related functions
1631# =====================================================================
1632
1633
1634def disk_usage(path):
1635    """Return disk usage statistics about the given path as a namedtuple
1636    including total, used and free space expressed in bytes plus the
1637    percentage usage.
1638    """
1639    return _psplatform.disk_usage(path)
1640
1641
1642def disk_partitions(all=False):
1643    """Return mounted partitions as a list of
1644    (device, mountpoint, fstype, opts) namedtuple.
1645    'opts' field is a raw string separated by commas indicating mount
1646    options which may vary depending on the platform.
1647
1648    If "all" parameter is False return physical devices only and ignore
1649    all others.
1650    """
1651    return _psplatform.disk_partitions(all)
1652
1653
1654def disk_io_counters(perdisk=False):
1655    """Return system disk I/O statistics as a namedtuple including
1656    the following fields:
1657
1658     - read_count:  number of reads
1659     - write_count: number of writes
1660     - read_bytes:  number of bytes read
1661     - write_bytes: number of bytes written
1662     - read_time:   time spent reading from disk (in milliseconds)
1663     - write_time:  time spent writing to disk (in milliseconds)
1664
1665    If perdisk is True return the same information for every
1666    physical disk installed on the system as a dictionary
1667    with partition names as the keys and the namedtuple
1668    described above as the values.
1669
1670    On recent Windows versions 'diskperf -y' command may need to be
1671    executed first otherwise this function won't find any disk.
1672    """
1673    rawdict = _psplatform.disk_io_counters()
1674    if not rawdict:
1675        raise RuntimeError("couldn't find any physical disk")
1676    if perdisk:
1677        for disk, fields in rawdict.items():
1678            rawdict[disk] = _common.sdiskio(*fields)
1679        return rawdict
1680    else:
1681        return _common.sdiskio(*[sum(x) for x in zip(*rawdict.values())])
1682
1683
1684# =====================================================================
1685# --- network related functions
1686# =====================================================================
1687
1688
1689def net_io_counters(pernic=False):
1690    """Return network I/O statistics as a namedtuple including
1691    the following fields:
1692
1693     - bytes_sent:   number of bytes sent
1694     - bytes_recv:   number of bytes received
1695     - packets_sent: number of packets sent
1696     - packets_recv: number of packets received
1697     - errin:        total number of errors while receiving
1698     - errout:       total number of errors while sending
1699     - dropin:       total number of incoming packets which were dropped
1700     - dropout:      total number of outgoing packets which were dropped
1701                     (always 0 on OSX and BSD)
1702
1703    If pernic is True return the same information for every
1704    network interface installed on the system as a dictionary
1705    with network interface names as the keys and the namedtuple
1706    described above as the values.
1707    """
1708    rawdict = _psplatform.net_io_counters()
1709    if not rawdict:
1710        raise RuntimeError("couldn't find any network interface")
1711    if pernic:
1712        for nic, fields in rawdict.items():
1713            rawdict[nic] = _common.snetio(*fields)
1714        return rawdict
1715    else:
1716        return _common.snetio(*[sum(x) for x in zip(*rawdict.values())])
1717
1718
1719def net_connections(kind='inet'):
1720    """Return system-wide connections as a list of
1721    (fd, family, type, laddr, raddr, status, pid) namedtuples.
1722    In case of limited privileges 'fd' and 'pid' may be set to -1
1723    and None respectively.
1724    The 'kind' parameter filters for connections that fit the
1725    following criteria:
1726
1727    Kind Value      Connections using
1728    inet            IPv4 and IPv6
1729    inet4           IPv4
1730    inet6           IPv6
1731    tcp             TCP
1732    tcp4            TCP over IPv4
1733    tcp6            TCP over IPv6
1734    udp             UDP
1735    udp4            UDP over IPv4
1736    udp6            UDP over IPv6
1737    unix            UNIX socket (both UDP and TCP protocols)
1738    all             the sum of all the possible families and protocols
1739
1740    On OSX this function requires root privileges.
1741    """
1742    return _psplatform.net_connections(kind)
1743
1744
1745def net_if_addrs():
1746    """Return the addresses associated to each NIC (network interface
1747    card) installed on the system as a dictionary whose keys are the
1748    NIC names and value is a list of namedtuples for each address
1749    assigned to the NIC. Each namedtuple includes 4 fields:
1750
1751     - family
1752     - address
1753     - netmask
1754     - broadcast
1755
1756    'family' can be either socket.AF_INET, socket.AF_INET6 or
1757    psutil.AF_LINK, which refers to a MAC address.
1758    'address' is the primary address, 'netmask' and 'broadcast'
1759    may be None.
1760    Note: you can have more than one address of the same family
1761    associated with each interface.
1762    """
1763    has_enums = sys.version_info >= (3, 4)
1764    if has_enums:
1765        import socket
1766    rawlist = _psplatform.net_if_addrs()
1767    rawlist.sort(key=lambda x: x[1])  # sort by family
1768    ret = collections.defaultdict(list)
1769    for name, fam, addr, mask, broadcast in rawlist:
1770        if has_enums:
1771            try:
1772                fam = socket.AddressFamily(fam)
1773            except ValueError:
1774                if os.name == 'nt' and fam == -1:
1775                    fam = _psplatform.AF_LINK
1776                elif (hasattr(_psplatform, "AF_LINK") and
1777                        _psplatform.AF_LINK == fam):
1778                    # Linux defines AF_LINK as an alias for AF_PACKET.
1779                    # We re-set the family here so that repr(family)
1780                    # will show AF_LINK rather than AF_PACKET
1781                    fam = _psplatform.AF_LINK
1782        ret[name].append(_common.snic(fam, addr, mask, broadcast))
1783    return dict(ret)
1784
1785
1786def net_if_stats():
1787    """Return information about each NIC (network interface card)
1788    installed on the system as a dictionary whose keys are the
1789    NIC names and value is a namedtuple with the following fields:
1790
1791     - isup: whether the interface is up (bool)
1792     - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or
1793               NIC_DUPLEX_UNKNOWN
1794     - speed: the NIC speed expressed in mega bits (MB); if it can't
1795              be determined (e.g. 'localhost') it will be set to 0.
1796     - mtu: the maximum transmission unit expressed in bytes.
1797    """
1798    return _psplatform.net_if_stats()
1799
1800
1801# =====================================================================
1802# --- other system related functions
1803# =====================================================================
1804
1805
1806def boot_time():
1807    """Return the system boot time expressed in seconds since the epoch."""
1808    # Note: we are not caching this because it is subject to
1809    # system clock updates.
1810    return _psplatform.boot_time()
1811
1812
1813def users():
1814    """Return users currently connected on the system as a list of
1815    namedtuples including the following fields.
1816
1817     - user: the name of the user
1818     - terminal: the tty or pseudo-tty associated with the user, if any.
1819     - host: the host name associated with the entry, if any.
1820     - started: the creation time as a floating point number expressed in
1821       seconds since the epoch.
1822    """
1823    return _psplatform.users()
1824
1825
1826def test():
1827    """List info of all currently running processes emulating ps aux
1828    output.
1829    """
1830    import datetime
1831
1832    today_day = datetime.date.today()
1833    templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s  %s"
1834    attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
1835             'create_time', 'memory_info']
1836    if _POSIX:
1837        attrs.append('uids')
1838        attrs.append('terminal')
1839    print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
1840                   "START", "TIME", "COMMAND"))
1841    for p in process_iter():
1842        try:
1843            pinfo = p.as_dict(attrs, ad_value='')
1844        except NoSuchProcess:
1845            pass
1846        else:
1847            if pinfo['create_time']:
1848                ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
1849                if ctime.date() == today_day:
1850                    ctime = ctime.strftime("%H:%M")
1851                else:
1852                    ctime = ctime.strftime("%b%d")
1853            else:
1854                ctime = ''
1855            cputime = time.strftime("%M:%S",
1856                                    time.localtime(sum(pinfo['cpu_times'])))
1857            try:
1858                user = p.username()
1859            except Error:
1860                user = ''
1861            if _WINDOWS and '\\' in user:
1862                user = user.split('\\')[1]
1863            vms = pinfo['memory_info'] and \
1864                int(pinfo['memory_info'].vms / 1024) or '?'
1865            rss = pinfo['memory_info'] and \
1866                int(pinfo['memory_info'].rss / 1024) or '?'
1867            memp = pinfo['memory_percent'] and \
1868                round(pinfo['memory_percent'], 1) or '?'
1869            print(templ % (
1870                user[:10],
1871                pinfo['pid'],
1872                pinfo['cpu_percent'],
1873                memp,
1874                vms,
1875                rss,
1876                pinfo.get('terminal', '') or '?',
1877                ctime,
1878                cputime,
1879                pinfo['name'].strip() or '?'))
1880
1881
1882del memoize, division
1883if sys.version_info < (3, 0):
1884    del num
1885
1886if __name__ == "__main__":
1887    test()
1888