1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""psutil is a cross-platform library for retrieving information on
8running processes and system utilization (CPU, memory, disks, network,
9sensors) in Python. Supported platforms:
10
11 - Linux
12 - Windows
13 - OSX
14 - FreeBSD
15 - OpenBSD
16 - NetBSD
17 - Sun Solaris
18 - AIX
19
20Works with Python versions from 2.6 to 3.X.
21"""
22
23from __future__ import division
24
25import collections
26import contextlib
27import datetime
28import errno
29import functools
30import os
31import signal
32import subprocess
33import sys
34import time
35import traceback
36try:
37    import pwd
38except ImportError:
39    pwd = None
40
41from . import _common
42from ._common import deprecated_method
43from ._common import memoize
44from ._common import memoize_when_activated
45from ._common import wrap_numbers as _wrap_numbers
46from ._compat import callable
47from ._compat import long
48from ._compat import PY3 as _PY3
49
50from ._common import STATUS_DEAD
51from ._common import STATUS_DISK_SLEEP
52from ._common import STATUS_IDLE  # bsd
53from ._common import STATUS_LOCKED
54from ._common import STATUS_RUNNING
55from ._common import STATUS_SLEEPING
56from ._common import STATUS_STOPPED
57from ._common import STATUS_TRACING_STOP
58from ._common import STATUS_WAITING  # bsd
59from ._common import STATUS_WAKING
60from ._common import STATUS_ZOMBIE
61
62from ._common import CONN_CLOSE
63from ._common import CONN_CLOSE_WAIT
64from ._common import CONN_CLOSING
65from ._common import CONN_ESTABLISHED
66from ._common import CONN_FIN_WAIT1
67from ._common import CONN_FIN_WAIT2
68from ._common import CONN_LAST_ACK
69from ._common import CONN_LISTEN
70from ._common import CONN_NONE
71from ._common import CONN_SYN_RECV
72from ._common import CONN_SYN_SENT
73from ._common import CONN_TIME_WAIT
74from ._common import NIC_DUPLEX_FULL
75from ._common import NIC_DUPLEX_HALF
76from ._common import NIC_DUPLEX_UNKNOWN
77
78from ._common import AIX
79from ._common import BSD
80from ._common import FREEBSD  # NOQA
81from ._common import LINUX
82from ._common import NETBSD  # NOQA
83from ._common import OPENBSD  # NOQA
84from ._common import OSX
85from ._common import POSIX  # NOQA
86from ._common import SUNOS
87from ._common import WINDOWS
88
89from ._exceptions import AccessDenied
90from ._exceptions import Error
91from ._exceptions import NoSuchProcess
92from ._exceptions import TimeoutExpired
93from ._exceptions import ZombieProcess
94
95if LINUX:
96    # This is public API and it will be retrieved from _pslinux.py
97    # via sys.modules.
98    PROCFS_PATH = "/proc"
99
100    from . import _pslinux as _psplatform
101
102    from ._pslinux import IOPRIO_CLASS_BE  # NOQA
103    from ._pslinux import IOPRIO_CLASS_IDLE  # NOQA
104    from ._pslinux import IOPRIO_CLASS_NONE  # NOQA
105    from ._pslinux import IOPRIO_CLASS_RT  # NOQA
106    # Linux >= 2.6.36
107    if _psplatform.HAS_PRLIMIT:
108        from ._psutil_linux import RLIM_INFINITY  # NOQA
109        from ._psutil_linux import RLIMIT_AS  # NOQA
110        from ._psutil_linux import RLIMIT_CORE  # NOQA
111        from ._psutil_linux import RLIMIT_CPU  # NOQA
112        from ._psutil_linux import RLIMIT_DATA  # NOQA
113        from ._psutil_linux import RLIMIT_FSIZE  # NOQA
114        from ._psutil_linux import RLIMIT_LOCKS  # NOQA
115        from ._psutil_linux import RLIMIT_MEMLOCK  # NOQA
116        from ._psutil_linux import RLIMIT_NOFILE  # NOQA
117        from ._psutil_linux import RLIMIT_NPROC  # NOQA
118        from ._psutil_linux import RLIMIT_RSS  # NOQA
119        from ._psutil_linux import RLIMIT_STACK  # NOQA
120        # Kinda ugly but considerably faster than using hasattr() and
121        # setattr() against the module object (we are at import time:
122        # speed matters).
123        from . import _psutil_linux
124        try:
125            RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE
126        except AttributeError:
127            pass
128        try:
129            RLIMIT_NICE = _psutil_linux.RLIMIT_NICE
130        except AttributeError:
131            pass
132        try:
133            RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO
134        except AttributeError:
135            pass
136        try:
137            RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME
138        except AttributeError:
139            pass
140        try:
141            RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING
142        except AttributeError:
143            pass
144
145elif WINDOWS:
146    from . import _pswindows as _psplatform
147    from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS  # NOQA
148    from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS  # NOQA
149    from ._psutil_windows import HIGH_PRIORITY_CLASS  # NOQA
150    from ._psutil_windows import IDLE_PRIORITY_CLASS  # NOQA
151    from ._psutil_windows import NORMAL_PRIORITY_CLASS  # NOQA
152    from ._psutil_windows import REALTIME_PRIORITY_CLASS  # NOQA
153    from ._pswindows import CONN_DELETE_TCB  # NOQA
154
155elif OSX:
156    from . import _psosx as _psplatform
157
158elif BSD:
159    from . import _psbsd as _psplatform
160
161elif SUNOS:
162    from . import _pssunos as _psplatform
163    from ._pssunos import CONN_BOUND  # NOQA
164    from ._pssunos import CONN_IDLE  # NOQA
165
166    # This is public writable API which is read from _pslinux.py and
167    # _pssunos.py via sys.modules.
168    PROCFS_PATH = "/proc"
169
170elif AIX:
171    from . import _psaix as _psplatform
172
173    # This is public API and it will be retrieved from _pslinux.py
174    # via sys.modules.
175    PROCFS_PATH = "/proc"
176
177else:  # pragma: no cover
178    raise NotImplementedError('platform %s is not supported' % sys.platform)
179
180
181__all__ = [
182    # exceptions
183    "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied",
184    "TimeoutExpired",
185
186    # constants
187    "version_info", "__version__",
188
189    "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
190    "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
191    "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED",
192
193    "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1",
194    "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
195    "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE",
196
197    "AF_LINK",
198
199    "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN",
200
201    "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED",
202
203    "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "OSX", "POSIX", "SUNOS",
204    "WINDOWS", "AIX",
205
206    # classes
207    "Process", "Popen",
208
209    # functions
210    "pid_exists", "pids", "process_iter", "wait_procs",             # proc
211    "virtual_memory", "swap_memory",                                # memory
212    "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count",   # cpu
213    "cpu_stats",  # "cpu_freq",
214    "net_io_counters", "net_connections", "net_if_addrs",           # network
215    "net_if_stats",
216    "disk_io_counters", "disk_partitions", "disk_usage",            # disk
217    # "sensors_temperatures", "sensors_battery", "sensors_fans"     # sensors
218    "users", "boot_time",                                           # others
219]
220__all__.extend(_psplatform.__extra__all__)
221__author__ = "Giampaolo Rodola'"
222__version__ = "5.4.3"
223version_info = tuple([int(num) for num in __version__.split('.')])
224AF_LINK = _psplatform.AF_LINK
225POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED
226POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN
227_TOTAL_PHYMEM = None
228_timer = getattr(time, 'monotonic', time.time)
229
230
231# Sanity check in case the user messed up with psutil installation
232# or did something weird with sys.path. In this case we might end
233# up importing a python module using a C extension module which
234# was compiled for a different version of psutil.
235# We want to prevent that by failing sooner rather than later.
236# See: https://github.com/giampaolo/psutil/issues/564
237if (int(__version__.replace('.', '')) !=
238        getattr(_psplatform.cext, 'version', None)):
239    msg = "version conflict: %r C extension module was built for another " \
240          "version of psutil" % getattr(_psplatform.cext, "__file__")
241    if hasattr(_psplatform.cext, 'version'):
242        msg += " (%s instead of %s)" % (
243            '.'.join([x for x in str(_psplatform.cext.version)]), __version__)
244    else:
245        msg += " (different than %s)" % __version__
246    msg += "; you may try to 'pip uninstall psutil', manually remove %s" % (
247        getattr(_psplatform.cext, "__file__",
248                "the existing psutil install directory"))
249    msg += " or clean the virtual env somehow, then reinstall"
250    raise ImportError(msg)
251
252
253# =====================================================================
254# --- Utils
255# =====================================================================
256
257
258if hasattr(_psplatform, 'ppid_map'):
259    # Faster version (Windows and Linux).
260    _ppid_map = _psplatform.ppid_map
261else:
262    def _ppid_map():
263        """Return a {pid: ppid, ...} dict for all running processes in
264        one shot. Used to speed up Process.children().
265        """
266        ret = {}
267        for pid in pids():
268            try:
269                proc = _psplatform.Process(pid)
270                ppid = proc.ppid()
271            except (NoSuchProcess, AccessDenied):
272                # Note: AccessDenied is unlikely to happen.
273                pass
274            else:
275                ret[pid] = ppid
276        return ret
277
278
279def _assert_pid_not_reused(fun):
280    """Decorator which raises NoSuchProcess in case a process is no
281    longer running or its PID has been reused.
282    """
283    @functools.wraps(fun)
284    def wrapper(self, *args, **kwargs):
285        if not self.is_running():
286            raise NoSuchProcess(self.pid, self._name)
287        return fun(self, *args, **kwargs)
288    return wrapper
289
290
291def _pprint_secs(secs):
292    """Format seconds in a human readable form."""
293    now = time.time()
294    secs_ago = int(now - secs)
295    if secs_ago < 60 * 60 * 24:
296        fmt = "%H:%M:%S"
297    else:
298        fmt = "%Y-%m-%d %H:%M:%S"
299    return datetime.datetime.fromtimestamp(secs).strftime(fmt)
300
301
302# =====================================================================
303# --- Process class
304# =====================================================================
305
306
307class Process(object):
308    """Represents an OS process with the given PID.
309    If PID is omitted current process PID (os.getpid()) is used.
310    Raise NoSuchProcess if PID does not exist.
311
312    Note that most of the methods of this class do not make sure
313    the PID of the process being queried has been reused over time.
314    That means you might end up retrieving an information referring
315    to another process in case the original one this instance
316    refers to is gone in the meantime.
317
318    The only exceptions for which process identity is pre-emptively
319    checked and guaranteed are:
320
321     - parent()
322     - children()
323     - nice() (set)
324     - ionice() (set)
325     - rlimit() (set)
326     - cpu_affinity (set)
327     - suspend()
328     - resume()
329     - send_signal()
330     - terminate()
331     - kill()
332
333    To prevent this problem for all other methods you can:
334     - use is_running() before querying the process
335     - if you're continuously iterating over a set of Process
336       instances use process_iter() which pre-emptively checks
337     process identity for every yielded instance
338    """
339
340    def __init__(self, pid=None):
341        self._init(pid)
342
343    def _init(self, pid, _ignore_nsp=False):
344        if pid is None:
345            pid = os.getpid()
346        else:
347            if not _PY3 and not isinstance(pid, (int, long)):
348                raise TypeError('pid must be an integer (got %r)' % pid)
349            if pid < 0:
350                raise ValueError('pid must be a positive integer (got %s)'
351                                 % pid)
352        self._pid = pid
353        self._name = None
354        self._exe = None
355        self._create_time = None
356        self._gone = False
357        self._hash = None
358        self._oneshot_inctx = False
359        # used for caching on Windows only (on POSIX ppid may change)
360        self._ppid = None
361        # platform-specific modules define an _psplatform.Process
362        # implementation class
363        self._proc = _psplatform.Process(pid)
364        self._last_sys_cpu_times = None
365        self._last_proc_cpu_times = None
366        # cache creation time for later use in is_running() method
367        try:
368            self.create_time()
369        except AccessDenied:
370            # We should never get here as AFAIK we're able to get
371            # process creation time on all platforms even as a
372            # limited user.
373            pass
374        except ZombieProcess:
375            # Zombies can still be queried by this class (although
376            # not always) and pids() return them so just go on.
377            pass
378        except NoSuchProcess:
379            if not _ignore_nsp:
380                msg = 'no process found with pid %s' % pid
381                raise NoSuchProcess(pid, None, msg)
382            else:
383                self._gone = True
384        # This pair is supposed to indentify a Process instance
385        # univocally over time (the PID alone is not enough as
386        # it might refer to a process whose PID has been reused).
387        # This will be used later in __eq__() and is_running().
388        self._ident = (self.pid, self._create_time)
389
390    def __str__(self):
391        try:
392            info = collections.OrderedDict()
393        except AttributeError:
394            info = {}  # Python 2.6
395        info["pid"] = self.pid
396        try:
397            info["name"] = self.name()
398            if self._create_time:
399                info['started'] = _pprint_secs(self._create_time)
400        except ZombieProcess:
401            info["status"] = "zombie"
402        except NoSuchProcess:
403            info["status"] = "terminated"
404        except AccessDenied:
405            pass
406        return "%s.%s(%s)" % (
407            self.__class__.__module__,
408            self.__class__.__name__,
409            ", ".join(["%s=%r" % (k, v) for k, v in info.items()]))
410
411    __repr__ = __str__
412
413    def __eq__(self, other):
414        # Test for equality with another Process object based
415        # on PID and creation time.
416        if not isinstance(other, Process):
417            return NotImplemented
418        return self._ident == other._ident
419
420    def __ne__(self, other):
421        return not self == other
422
423    def __hash__(self):
424        if self._hash is None:
425            self._hash = hash(self._ident)
426        return self._hash
427
428    @property
429    def pid(self):
430        """The process PID."""
431        return self._pid
432
433    # --- utility methods
434
435    @contextlib.contextmanager
436    def oneshot(self):
437        """Utility context manager which considerably speeds up the
438        retrieval of multiple process information at the same time.
439
440        Internally different process info (e.g. name, ppid, uids,
441        gids, ...) may be fetched by using the same routine, but
442        only one information is returned and the others are discarded.
443        When using this context manager the internal routine is
444        executed once (in the example below on name()) and the
445        other info are cached.
446
447        The cache is cleared when exiting the context manager block.
448        The advice is to use this every time you retrieve more than
449        one information about the process. If you're lucky, you'll
450        get a hell of a speedup.
451
452        >>> import psutil
453        >>> p = psutil.Process()
454        >>> with p.oneshot():
455        ...     p.name()  # collect multiple info
456        ...     p.cpu_times()  # return cached value
457        ...     p.cpu_percent()  # return cached value
458        ...     p.create_time()  # return cached value
459        ...
460        >>>
461        """
462        if self._oneshot_inctx:
463            # NOOP: this covers the use case where the user enters the
464            # context twice. Since as_dict() internally uses oneshot()
465            # I expect that the code below will be a pretty common
466            # "mistake" that the user will make, so let's guard
467            # against that:
468            #
469            # >>> with p.oneshot():
470            # ...    p.as_dict()
471            # ...
472            yield
473        else:
474            self._oneshot_inctx = True
475            try:
476                # cached in case cpu_percent() is used
477                self.cpu_times.cache_activate()
478                # cached in case memory_percent() is used
479                self.memory_info.cache_activate()
480                # cached in case parent() is used
481                self.ppid.cache_activate()
482                # cached in case username() is used
483                if POSIX:
484                    self.uids.cache_activate()
485                # specific implementation cache
486                self._proc.oneshot_enter()
487                yield
488            finally:
489                self.cpu_times.cache_deactivate()
490                self.memory_info.cache_deactivate()
491                self.ppid.cache_deactivate()
492                if POSIX:
493                    self.uids.cache_deactivate()
494                self._proc.oneshot_exit()
495                self._oneshot_inctx = False
496
497    def as_dict(self, attrs=None, ad_value=None):
498        """Utility method returning process information as a
499        hashable dictionary.
500        If *attrs* is specified it must be a list of strings
501        reflecting available Process class' attribute names
502        (e.g. ['cpu_times', 'name']) else all public (read
503        only) attributes are assumed.
504        *ad_value* is the value which gets assigned in case
505        AccessDenied or ZombieProcess exception is raised when
506        retrieving that particular process information.
507        """
508        valid_names = _as_dict_attrnames
509        if attrs is not None:
510            if not isinstance(attrs, (list, tuple, set, frozenset)):
511                raise TypeError("invalid attrs type %s" % type(attrs))
512            attrs = set(attrs)
513            invalid_names = attrs - valid_names
514            if invalid_names:
515                raise ValueError("invalid attr name%s %s" % (
516                    "s" if len(invalid_names) > 1 else "",
517                    ", ".join(map(repr, invalid_names))))
518
519        retdict = dict()
520        ls = attrs or valid_names
521        with self.oneshot():
522            for name in ls:
523                try:
524                    if name == 'pid':
525                        ret = self.pid
526                    else:
527                        meth = getattr(self, name)
528                        ret = meth()
529                except (AccessDenied, ZombieProcess):
530                    ret = ad_value
531                except NotImplementedError:
532                    # in case of not implemented functionality (may happen
533                    # on old or exotic systems) we want to crash only if
534                    # the user explicitly asked for that particular attr
535                    if attrs:
536                        raise
537                    continue
538                retdict[name] = ret
539        return retdict
540
541    def parent(self):
542        """Return the parent process as a Process object pre-emptively
543        checking whether PID has been reused.
544        If no parent is known return None.
545        """
546        ppid = self.ppid()
547        if ppid is not None:
548            ctime = self.create_time()
549            try:
550                parent = Process(ppid)
551                if parent.create_time() <= ctime:
552                    return parent
553                # ...else ppid has been reused by another process
554            except NoSuchProcess:
555                pass
556
557    def is_running(self):
558        """Return whether this process is running.
559        It also checks if PID has been reused by another process in
560        which case return False.
561        """
562        if self._gone:
563            return False
564        try:
565            # Checking if PID is alive is not enough as the PID might
566            # have been reused by another process: we also want to
567            # verify process identity.
568            # Process identity / uniqueness over time is guaranteed by
569            # (PID + creation time) and that is verified in __eq__.
570            return self == Process(self.pid)
571        except ZombieProcess:
572            # We should never get here as it's already handled in
573            # Process.__init__; here just for extra safety.
574            return True
575        except NoSuchProcess:
576            self._gone = True
577            return False
578
579    # --- actual API
580
581    @memoize_when_activated
582    def ppid(self):
583        """The process parent PID.
584        On Windows the return value is cached after first call.
585        """
586        # On POSIX we don't want to cache the ppid as it may unexpectedly
587        # change to 1 (init) in case this process turns into a zombie:
588        # https://github.com/giampaolo/psutil/issues/321
589        # http://stackoverflow.com/questions/356722/
590
591        # XXX should we check creation time here rather than in
592        # Process.parent()?
593        if POSIX:
594            return self._proc.ppid()
595        else:  # pragma: no cover
596            self._ppid = self._ppid or self._proc.ppid()
597            return self._ppid
598
599    def name(self):
600        """The process name. The return value is cached after first call."""
601        # Process name is only cached on Windows as on POSIX it may
602        # change, see:
603        # https://github.com/giampaolo/psutil/issues/692
604        if WINDOWS and self._name is not None:
605            return self._name
606        name = self._proc.name()
607        if POSIX and len(name) >= 15:
608            # On UNIX the name gets truncated to the first 15 characters.
609            # If it matches the first part of the cmdline we return that
610            # one instead because it's usually more explicative.
611            # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon".
612            try:
613                cmdline = self.cmdline()
614            except AccessDenied:
615                pass
616            else:
617                if cmdline:
618                    extended_name = os.path.basename(cmdline[0])
619                    if extended_name.startswith(name):
620                        name = extended_name
621        self._name = name
622        self._proc._name = name
623        return name
624
625    def exe(self):
626        """The process executable as an absolute path.
627        May also be an empty string.
628        The return value is cached after first call.
629        """
630        def guess_it(fallback):
631            # try to guess exe from cmdline[0] in absence of a native
632            # exe representation
633            cmdline = self.cmdline()
634            if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'):
635                exe = cmdline[0]  # the possible exe
636                # Attempt to guess only in case of an absolute path.
637                # It is not safe otherwise as the process might have
638                # changed cwd.
639                if (os.path.isabs(exe) and
640                        os.path.isfile(exe) and
641                        os.access(exe, os.X_OK)):
642                    return exe
643            if isinstance(fallback, AccessDenied):
644                raise fallback
645            return fallback
646
647        if self._exe is None:
648            try:
649                exe = self._proc.exe()
650            except AccessDenied as err:
651                return guess_it(fallback=err)
652            else:
653                if not exe:
654                    # underlying implementation can legitimately return an
655                    # empty string; if that's the case we don't want to
656                    # raise AD while guessing from the cmdline
657                    try:
658                        exe = guess_it(fallback=exe)
659                    except AccessDenied:
660                        pass
661                self._exe = exe
662        return self._exe
663
664    def cmdline(self):
665        """The command line this process has been called with."""
666        return self._proc.cmdline()
667
668    def status(self):
669        """The process current status as a STATUS_* constant."""
670        try:
671            return self._proc.status()
672        except ZombieProcess:
673            return STATUS_ZOMBIE
674
675    def username(self):
676        """The name of the user that owns the process.
677        On UNIX this is calculated by using *real* process uid.
678        """
679        if POSIX:
680            if pwd is None:
681                # might happen if python was installed from sources
682                raise ImportError(
683                    "requires pwd module shipped with standard python")
684            real_uid = self.uids().real
685            try:
686                return pwd.getpwuid(real_uid).pw_name
687            except KeyError:
688                # the uid can't be resolved by the system
689                return str(real_uid)
690        else:
691            return self._proc.username()
692
693    def create_time(self):
694        """The process creation time as a floating point number
695        expressed in seconds since the epoch, in UTC.
696        The return value is cached after first call.
697        """
698        if self._create_time is None:
699            self._create_time = self._proc.create_time()
700        return self._create_time
701
702    def cwd(self):
703        """Process current working directory as an absolute path."""
704        return self._proc.cwd()
705
706    def nice(self, value=None):
707        """Get or set process niceness (priority)."""
708        if value is None:
709            return self._proc.nice_get()
710        else:
711            if not self.is_running():
712                raise NoSuchProcess(self.pid, self._name)
713            self._proc.nice_set(value)
714
715    if POSIX:
716
717        @memoize_when_activated
718        def uids(self):
719            """Return process UIDs as a (real, effective, saved)
720            namedtuple.
721            """
722            return self._proc.uids()
723
724        def gids(self):
725            """Return process GIDs as a (real, effective, saved)
726            namedtuple.
727            """
728            return self._proc.gids()
729
730        def terminal(self):
731            """The terminal associated with this process, if any,
732            else None.
733            """
734            return self._proc.terminal()
735
736        def num_fds(self):
737            """Return the number of file descriptors opened by this
738            process (POSIX only).
739            """
740            return self._proc.num_fds()
741
742    # Linux, BSD, AIX and Windows only
743    if hasattr(_psplatform.Process, "io_counters"):
744
745        def io_counters(self):
746            """Return process I/O statistics as a
747            (read_count, write_count, read_bytes, write_bytes)
748            namedtuple.
749            Those are the number of read/write calls performed and the
750            amount of bytes read and written by the process.
751            """
752            return self._proc.io_counters()
753
754    # Linux and Windows >= Vista only
755    if hasattr(_psplatform.Process, "ionice_get"):
756
757        def ionice(self, ioclass=None, value=None):
758            """Get or set process I/O niceness (priority).
759
760            On Linux *ioclass* is one of the IOPRIO_CLASS_* constants.
761            *value* is a number which goes from 0 to 7. The higher the
762            value, the lower the I/O priority of the process.
763
764            On Windows only *ioclass* is used and it can be set to 2
765            (normal), 1 (low) or 0 (very low).
766
767            Available on Linux and Windows > Vista only.
768            """
769            if ioclass is None:
770                if value is not None:
771                    raise ValueError("'ioclass' argument must be specified")
772                return self._proc.ionice_get()
773            else:
774                return self._proc.ionice_set(ioclass, value)
775
776    # Linux only
777    if hasattr(_psplatform.Process, "rlimit"):
778
779        def rlimit(self, resource, limits=None):
780            """Get or set process resource limits as a (soft, hard)
781            tuple.
782
783            *resource* is one of the RLIMIT_* constants.
784            *limits* is supposed to be a (soft, hard)  tuple.
785
786            See "man prlimit" for further info.
787            Available on Linux only.
788            """
789            if limits is None:
790                return self._proc.rlimit(resource)
791            else:
792                return self._proc.rlimit(resource, limits)
793
794    # Windows, Linux and FreeBSD only
795    if hasattr(_psplatform.Process, "cpu_affinity_get"):
796
797        def cpu_affinity(self, cpus=None):
798            """Get or set process CPU affinity.
799            If specified, *cpus* must be a list of CPUs for which you
800            want to set the affinity (e.g. [0, 1]).
801            If an empty list is passed, all egible CPUs are assumed
802            (and set).
803            (Windows, Linux and BSD only).
804            """
805            # Automatically remove duplicates both on get and
806            # set (for get it's not really necessary, it's
807            # just for extra safety).
808            if cpus is None:
809                return list(set(self._proc.cpu_affinity_get()))
810            else:
811                if not cpus:
812                    if hasattr(self._proc, "_get_eligible_cpus"):
813                        cpus = self._proc._get_eligible_cpus()
814                    else:
815                        cpus = tuple(range(len(cpu_times(percpu=True))))
816                self._proc.cpu_affinity_set(list(set(cpus)))
817
818    # Linux, FreeBSD, SunOS
819    if hasattr(_psplatform.Process, "cpu_num"):
820
821        def cpu_num(self):
822            """Return what CPU this process is currently running on.
823            The returned number should be <= psutil.cpu_count()
824            and <= len(psutil.cpu_percent(percpu=True)).
825            It may be used in conjunction with
826            psutil.cpu_percent(percpu=True) to observe the system
827            workload distributed across CPUs.
828            """
829            return self._proc.cpu_num()
830
831    # Linux, OSX and Windows only
832    if hasattr(_psplatform.Process, "environ"):
833
834        def environ(self):
835            """The environment variables of the process as a dict.  Note: this
836            might not reflect changes made after the process started.  """
837            return self._proc.environ()
838
839    if WINDOWS:
840
841        def num_handles(self):
842            """Return the number of handles opened by this process
843            (Windows only).
844            """
845            return self._proc.num_handles()
846
847    def num_ctx_switches(self):
848        """Return the number of voluntary and involuntary context
849        switches performed by this process.
850        """
851        return self._proc.num_ctx_switches()
852
853    def num_threads(self):
854        """Return the number of threads used by this process."""
855        return self._proc.num_threads()
856
857    if hasattr(_psplatform.Process, "threads"):
858
859        def threads(self):
860            """Return threads opened by process as a list of
861            (id, user_time, system_time) namedtuples representing
862            thread id and thread CPU times (user/system).
863            On OpenBSD this method requires root access.
864            """
865            return self._proc.threads()
866
867    @_assert_pid_not_reused
868    def children(self, recursive=False):
869        """Return the children of this process as a list of Process
870        instances, pre-emptively checking whether PID has been reused.
871        If *recursive* is True return all the parent descendants.
872
873        Example (A == this process):
874
875         A ─┐
876877            ├─ B (child) ─┐
878            │             └─ X (grandchild) ─┐
879            │                                └─ Y (great grandchild)
880            ├─ C (child)
881            └─ D (child)
882
883        >>> import psutil
884        >>> p = psutil.Process()
885        >>> p.children()
886        B, C, D
887        >>> p.children(recursive=True)
888        B, X, Y, C, D
889
890        Note that in the example above if process X disappears
891        process Y won't be listed as the reference to process A
892        is lost.
893        """
894        ppid_map = _ppid_map()
895        ret = []
896        if not recursive:
897            for pid, ppid in ppid_map.items():
898                if ppid == self.pid:
899                    try:
900                        child = Process(pid)
901                        # if child happens to be older than its parent
902                        # (self) it means child's PID has been reused
903                        if self.create_time() <= child.create_time():
904                            ret.append(child)
905                    except (NoSuchProcess, ZombieProcess):
906                        pass
907        else:
908            # Construct a {pid: [child pids]} dict
909            reverse_ppid_map = collections.defaultdict(list)
910            for pid, ppid in ppid_map.items():
911                reverse_ppid_map[ppid].append(pid)
912            # Recursively traverse that dict, starting from self.pid,
913            # such that we only call Process() on actual children
914            seen = set()
915            stack = [self.pid]
916            while stack:
917                pid = stack.pop()
918                if pid in seen:
919                    # Since pids can be reused while the ppid_map is
920                    # constructed, there may be rare instances where
921                    # there's a cycle in the recorded process "tree".
922                    continue
923                seen.add(pid)
924                for child_pid in reverse_ppid_map[pid]:
925                    try:
926                        child = Process(child_pid)
927                        # if child happens to be older than its parent
928                        # (self) it means child's PID has been reused
929                        intime = self.create_time() <= child.create_time()
930                        if intime:
931                            ret.append(child)
932                            stack.append(child_pid)
933                    except (NoSuchProcess, ZombieProcess):
934                        pass
935        return ret
936
937    def cpu_percent(self, interval=None):
938        """Return a float representing the current process CPU
939        utilization as a percentage.
940
941        When *interval* is 0.0 or None (default) compares process times
942        to system CPU times elapsed since last call, returning
943        immediately (non-blocking). That means that the first time
944        this is called it will return a meaningful 0.0 value.
945
946        When *interval* is > 0.0 compares process times to system CPU
947        times elapsed before and after the interval (blocking).
948
949        In this case is recommended for accuracy that this function
950        be called with at least 0.1 seconds between calls.
951
952        A value > 100.0 can be returned in case of processes running
953        multiple threads on different CPU cores.
954
955        The returned value is explicitly NOT split evenly between
956        all available logical CPUs. This means that a busy loop process
957        running on a system with 2 logical CPUs will be reported as
958        having 100% CPU utilization instead of 50%.
959
960        Examples:
961
962          >>> import psutil
963          >>> p = psutil.Process(os.getpid())
964          >>> # blocking
965          >>> p.cpu_percent(interval=1)
966          2.0
967          >>> # non-blocking (percentage since last call)
968          >>> p.cpu_percent(interval=None)
969          2.9
970          >>>
971        """
972        blocking = interval is not None and interval > 0.0
973        if interval is not None and interval < 0:
974            raise ValueError("interval is not positive (got %r)" % interval)
975        num_cpus = cpu_count() or 1
976
977        def timer():
978            return _timer() * num_cpus
979
980        if blocking:
981            st1 = timer()
982            pt1 = self._proc.cpu_times()
983            time.sleep(interval)
984            st2 = timer()
985            pt2 = self._proc.cpu_times()
986        else:
987            st1 = self._last_sys_cpu_times
988            pt1 = self._last_proc_cpu_times
989            st2 = timer()
990            pt2 = self._proc.cpu_times()
991            if st1 is None or pt1 is None:
992                self._last_sys_cpu_times = st2
993                self._last_proc_cpu_times = pt2
994                return 0.0
995
996        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
997        delta_time = st2 - st1
998        # reset values for next call in case of interval == None
999        self._last_sys_cpu_times = st2
1000        self._last_proc_cpu_times = pt2
1001
1002        try:
1003            # This is the utilization split evenly between all CPUs.
1004            # E.g. a busy loop process on a 2-CPU-cores system at this
1005            # point is reported as 50% instead of 100%.
1006            overall_cpus_percent = ((delta_proc / delta_time) * 100)
1007        except ZeroDivisionError:
1008            # interval was too low
1009            return 0.0
1010        else:
1011            # Note 1:
1012            # in order to emulate "top" we multiply the value for the num
1013            # of CPU cores. This way the busy process will be reported as
1014            # having 100% (or more) usage.
1015            #
1016            # Note 2:
1017            # taskmgr.exe on Windows differs in that it will show 50%
1018            # instead.
1019            #
1020            # Note 3:
1021            # a percentage > 100 is legitimate as it can result from a
1022            # process with multiple threads running on different CPU
1023            # cores (top does the same), see:
1024            # http://stackoverflow.com/questions/1032357
1025            # https://github.com/giampaolo/psutil/issues/474
1026            single_cpu_percent = overall_cpus_percent * num_cpus
1027            return round(single_cpu_percent, 1)
1028
1029    @memoize_when_activated
1030    def cpu_times(self):
1031        """Return a (user, system, children_user, children_system)
1032        namedtuple representing the accumulated process time, in
1033        seconds.
1034        This is similar to os.times() but per-process.
1035        On OSX and Windows children_user and children_system are
1036        always set to 0.
1037        """
1038        return self._proc.cpu_times()
1039
1040    @memoize_when_activated
1041    def memory_info(self):
1042        """Return a namedtuple with variable fields depending on the
1043        platform, representing memory information about the process.
1044
1045        The "portable" fields available on all plaforms are `rss` and `vms`.
1046
1047        All numbers are expressed in bytes.
1048        """
1049        return self._proc.memory_info()
1050
1051    @deprecated_method(replacement="memory_info")
1052    def memory_info_ex(self):
1053        return self.memory_info()
1054
1055    def memory_full_info(self):
1056        """This method returns the same information as memory_info(),
1057        plus, on some platform (Linux, OSX, Windows), also provides
1058        additional metrics (USS, PSS and swap).
1059        The additional metrics provide a better representation of actual
1060        process memory usage.
1061
1062        Namely USS is the memory which is unique to a process and which
1063        would be freed if the process was terminated right now.
1064
1065        It does so by passing through the whole process address.
1066        As such it usually requires higher user privileges than
1067        memory_info() and is considerably slower.
1068        """
1069        return self._proc.memory_full_info()
1070
1071    def memory_percent(self, memtype="rss"):
1072        """Compare process memory to total physical system memory and
1073        calculate process memory utilization as a percentage.
1074        *memtype* argument is a string that dictates what type of
1075        process memory you want to compare against (defaults to "rss").
1076        The list of available strings can be obtained like this:
1077
1078        >>> psutil.Process().memory_info()._fields
1079        ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss')
1080        """
1081        valid_types = list(_psplatform.pfullmem._fields)
1082        if memtype not in valid_types:
1083            raise ValueError("invalid memtype %r; valid types are %r" % (
1084                memtype, tuple(valid_types)))
1085        fun = self.memory_info if memtype in _psplatform.pmem._fields else \
1086            self.memory_full_info
1087        metrics = fun()
1088        value = getattr(metrics, memtype)
1089
1090        # use cached value if available
1091        total_phymem = _TOTAL_PHYMEM or virtual_memory().total
1092        if not total_phymem > 0:
1093            # we should never get here
1094            raise ValueError(
1095                "can't calculate process memory percent because "
1096                "total physical system memory is not positive (%r)"
1097                % total_phymem)
1098        return (value / float(total_phymem)) * 100
1099
1100    if hasattr(_psplatform.Process, "memory_maps"):
1101        # Available everywhere except OpenBSD and NetBSD.
1102        def memory_maps(self, grouped=True):
1103            """Return process' mapped memory regions as a list of namedtuples
1104            whose fields are variable depending on the platform.
1105
1106            If *grouped* is True the mapped regions with the same 'path'
1107            are grouped together and the different memory fields are summed.
1108
1109            If *grouped* is False every mapped region is shown as a single
1110            entity and the namedtuple will also include the mapped region's
1111            address space ('addr') and permission set ('perms').
1112            """
1113            it = self._proc.memory_maps()
1114            if grouped:
1115                d = {}
1116                for tupl in it:
1117                    path = tupl[2]
1118                    nums = tupl[3:]
1119                    try:
1120                        d[path] = map(lambda x, y: x + y, d[path], nums)
1121                    except KeyError:
1122                        d[path] = nums
1123                nt = _psplatform.pmmap_grouped
1124                return [nt(path, *d[path]) for path in d]  # NOQA
1125            else:
1126                nt = _psplatform.pmmap_ext
1127                return [nt(*x) for x in it]
1128
1129    def open_files(self):
1130        """Return files opened by process as a list of
1131        (path, fd) namedtuples including the absolute file name
1132        and file descriptor number.
1133        """
1134        return self._proc.open_files()
1135
1136    def connections(self, kind='inet'):
1137        """Return socket connections opened by process as a list of
1138        (fd, family, type, laddr, raddr, status) namedtuples.
1139        The *kind* parameter filters for connections that match the
1140        following criteria:
1141
1142        +------------+----------------------------------------------------+
1143        | Kind Value | Connections using                                  |
1144        +------------+----------------------------------------------------+
1145        | inet       | IPv4 and IPv6                                      |
1146        | inet4      | IPv4                                               |
1147        | inet6      | IPv6                                               |
1148        | tcp        | TCP                                                |
1149        | tcp4       | TCP over IPv4                                      |
1150        | tcp6       | TCP over IPv6                                      |
1151        | udp        | UDP                                                |
1152        | udp4       | UDP over IPv4                                      |
1153        | udp6       | UDP over IPv6                                      |
1154        | unix       | UNIX socket (both UDP and TCP protocols)           |
1155        | all        | the sum of all the possible families and protocols |
1156        +------------+----------------------------------------------------+
1157        """
1158        return self._proc.connections(kind)
1159
1160    # --- signals
1161
1162    if POSIX:
1163        def _send_signal(self, sig):
1164            assert not self.pid < 0, self.pid
1165            if self.pid == 0:
1166                # see "man 2 kill"
1167                raise ValueError(
1168                    "preventing sending signal to process with PID 0 as it "
1169                    "would affect every process in the process group of the "
1170                    "calling process (os.getpid()) instead of PID 0")
1171            try:
1172                os.kill(self.pid, sig)
1173            except OSError as err:
1174                if err.errno == errno.ESRCH:
1175                    if OPENBSD and pid_exists(self.pid):
1176                        # We do this because os.kill() lies in case of
1177                        # zombie processes.
1178                        raise ZombieProcess(self.pid, self._name, self._ppid)
1179                    else:
1180                        self._gone = True
1181                        raise NoSuchProcess(self.pid, self._name)
1182                if err.errno in (errno.EPERM, errno.EACCES):
1183                    raise AccessDenied(self.pid, self._name)
1184                raise
1185
1186    @_assert_pid_not_reused
1187    def send_signal(self, sig):
1188        """Send a signal *sig* to process pre-emptively checking
1189        whether PID has been reused (see signal module constants) .
1190        On Windows only SIGTERM is valid and is treated as an alias
1191        for kill().
1192        """
1193        if POSIX:
1194            self._send_signal(sig)
1195        else:  # pragma: no cover
1196            if sig == signal.SIGTERM:
1197                self._proc.kill()
1198            # py >= 2.7
1199            elif sig in (getattr(signal, "CTRL_C_EVENT", object()),
1200                         getattr(signal, "CTRL_BREAK_EVENT", object())):
1201                self._proc.send_signal(sig)
1202            else:
1203                raise ValueError(
1204                    "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
1205                    "are supported on Windows")
1206
1207    @_assert_pid_not_reused
1208    def suspend(self):
1209        """Suspend process execution with SIGSTOP pre-emptively checking
1210        whether PID has been reused.
1211        On Windows this has the effect ot suspending all process threads.
1212        """
1213        if POSIX:
1214            self._send_signal(signal.SIGSTOP)
1215        else:  # pragma: no cover
1216            self._proc.suspend()
1217
1218    @_assert_pid_not_reused
1219    def resume(self):
1220        """Resume process execution with SIGCONT pre-emptively checking
1221        whether PID has been reused.
1222        On Windows this has the effect of resuming all process threads.
1223        """
1224        if POSIX:
1225            self._send_signal(signal.SIGCONT)
1226        else:  # pragma: no cover
1227            self._proc.resume()
1228
1229    @_assert_pid_not_reused
1230    def terminate(self):
1231        """Terminate the process with SIGTERM pre-emptively checking
1232        whether PID has been reused.
1233        On Windows this is an alias for kill().
1234        """
1235        if POSIX:
1236            self._send_signal(signal.SIGTERM)
1237        else:  # pragma: no cover
1238            self._proc.kill()
1239
1240    @_assert_pid_not_reused
1241    def kill(self):
1242        """Kill the current process with SIGKILL pre-emptively checking
1243        whether PID has been reused.
1244        """
1245        if POSIX:
1246            self._send_signal(signal.SIGKILL)
1247        else:  # pragma: no cover
1248            self._proc.kill()
1249
1250    def wait(self, timeout=None):
1251        """Wait for process to terminate and, if process is a children
1252        of os.getpid(), also return its exit code, else None.
1253
1254        If the process is already terminated immediately return None
1255        instead of raising NoSuchProcess.
1256
1257        If *timeout* (in seconds) is specified and process is still
1258        alive raise TimeoutExpired.
1259
1260        To wait for multiple Process(es) use psutil.wait_procs().
1261        """
1262        if timeout is not None and not timeout >= 0:
1263            raise ValueError("timeout must be a positive integer")
1264        return self._proc.wait(timeout)
1265
1266
1267# =====================================================================
1268# --- Popen class
1269# =====================================================================
1270
1271
1272class Popen(Process):
1273    """A more convenient interface to stdlib subprocess.Popen class.
1274    It starts a sub process and deals with it exactly as when using
1275    subprocess.Popen class but in addition also provides all the
1276    properties and methods of psutil.Process class as a unified
1277    interface:
1278
1279      >>> import psutil
1280      >>> from subprocess import PIPE
1281      >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE)
1282      >>> p.name()
1283      'python'
1284      >>> p.uids()
1285      user(real=1000, effective=1000, saved=1000)
1286      >>> p.username()
1287      'giampaolo'
1288      >>> p.communicate()
1289      ('hi\n', None)
1290      >>> p.terminate()
1291      >>> p.wait(timeout=2)
1292      0
1293      >>>
1294
1295    For method names common to both classes such as kill(), terminate()
1296    and wait(), psutil.Process implementation takes precedence.
1297
1298    Unlike subprocess.Popen this class pre-emptively checks whether PID
1299    has been reused on send_signal(), terminate() and kill() so that
1300    you don't accidentally terminate another process, fixing
1301    http://bugs.python.org/issue6973.
1302
1303    For a complete documentation refer to:
1304    http://docs.python.org/library/subprocess.html
1305    """
1306
1307    def __init__(self, *args, **kwargs):
1308        # Explicitly avoid to raise NoSuchProcess in case the process
1309        # spawned by subprocess.Popen terminates too quickly, see:
1310        # https://github.com/giampaolo/psutil/issues/193
1311        self.__subproc = subprocess.Popen(*args, **kwargs)
1312        self._init(self.__subproc.pid, _ignore_nsp=True)
1313
1314    def __dir__(self):
1315        return sorted(set(dir(Popen) + dir(subprocess.Popen)))
1316
1317    def __enter__(self):
1318        if hasattr(self.__subproc, '__enter__'):
1319            self.__subproc.__enter__()
1320        return self
1321
1322    def __exit__(self, *args, **kwargs):
1323        if hasattr(self.__subproc, '__exit__'):
1324            return self.__subproc.__exit__(*args, **kwargs)
1325        else:
1326            if self.stdout:
1327                self.stdout.close()
1328            if self.stderr:
1329                self.stderr.close()
1330            try:
1331                # Flushing a BufferedWriter may raise an error.
1332                if self.stdin:
1333                    self.stdin.close()
1334            finally:
1335                # Wait for the process to terminate, to avoid zombies.
1336                self.wait()
1337
1338    def __getattribute__(self, name):
1339        try:
1340            return object.__getattribute__(self, name)
1341        except AttributeError:
1342            try:
1343                return object.__getattribute__(self.__subproc, name)
1344            except AttributeError:
1345                raise AttributeError("%s instance has no attribute '%s'"
1346                                     % (self.__class__.__name__, name))
1347
1348    def wait(self, timeout=None):
1349        if self.__subproc.returncode is not None:
1350            return self.__subproc.returncode
1351        ret = super(Popen, self).wait(timeout)
1352        self.__subproc.returncode = ret
1353        return ret
1354
1355
1356# The valid attr names which can be processed by Process.as_dict().
1357_as_dict_attrnames = set(
1358    [x for x in dir(Process) if not x.startswith('_') and x not in
1359     ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
1360      'is_running', 'as_dict', 'parent', 'children', 'rlimit',
1361      'memory_info_ex', 'oneshot']])
1362
1363
1364# =====================================================================
1365# --- system processes related functions
1366# =====================================================================
1367
1368
1369def pids():
1370    """Return a list of current running PIDs."""
1371    return _psplatform.pids()
1372
1373
1374def pid_exists(pid):
1375    """Return True if given PID exists in the current process list.
1376    This is faster than doing "pid in psutil.pids()" and
1377    should be preferred.
1378    """
1379    if pid < 0:
1380        return False
1381    elif pid == 0 and POSIX:
1382        # On POSIX we use os.kill() to determine PID existence.
1383        # According to "man 2 kill" PID 0 has a special meaning
1384        # though: it refers to <<every process in the process
1385        # group of the calling process>> and that is not we want
1386        # to do here.
1387        return pid in pids()
1388    else:
1389        return _psplatform.pid_exists(pid)
1390
1391
1392_pmap = {}
1393
1394
1395def process_iter(attrs=None, ad_value=None):
1396    """Return a generator yielding a Process instance for all
1397    running processes.
1398
1399    Every new Process instance is only created once and then cached
1400    into an internal table which is updated every time this is used.
1401
1402    Cached Process instances are checked for identity so that you're
1403    safe in case a PID has been reused by another process, in which
1404    case the cached instance is updated.
1405
1406    The sorting order in which processes are yielded is based on
1407    their PIDs.
1408
1409    *attrs* and *ad_value* have the same meaning as in
1410    Process.as_dict(). If *attrs* is specified as_dict() is called
1411    and the resulting dict is stored as a 'info' attribute attached
1412    to returned Process instance.
1413    If *attrs* is an empty list it will retrieve all process info
1414    (slow).
1415    """
1416    def add(pid):
1417        proc = Process(pid)
1418        if attrs is not None:
1419            proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value)
1420        _pmap[proc.pid] = proc
1421        return proc
1422
1423    def remove(pid):
1424        _pmap.pop(pid, None)
1425
1426    a = set(pids())
1427    b = set(_pmap.keys())
1428    new_pids = a - b
1429    gone_pids = b - a
1430
1431    for pid in gone_pids:
1432        remove(pid)
1433    for pid, proc in sorted(list(_pmap.items()) +
1434                            list(dict.fromkeys(new_pids).items())):
1435        try:
1436            if proc is None:  # new process
1437                yield add(pid)
1438            else:
1439                # use is_running() to check whether PID has been reused by
1440                # another process in which case yield a new Process instance
1441                if proc.is_running():
1442                    if attrs is not None:
1443                        proc.info = proc.as_dict(
1444                            attrs=attrs, ad_value=ad_value)
1445                    yield proc
1446                else:
1447                    yield add(pid)
1448        except NoSuchProcess:
1449            remove(pid)
1450        except AccessDenied:
1451            # Process creation time can't be determined hence there's
1452            # no way to tell whether the pid of the cached process
1453            # has been reused. Just return the cached version.
1454            if proc is None and pid in _pmap:
1455                try:
1456                    yield _pmap[pid]
1457                except KeyError:
1458                    # If we get here it is likely that 2 threads were
1459                    # using process_iter().
1460                    pass
1461            else:
1462                raise
1463
1464
1465def wait_procs(procs, timeout=None, callback=None):
1466    """Convenience function which waits for a list of processes to
1467    terminate.
1468
1469    Return a (gone, alive) tuple indicating which processes
1470    are gone and which ones are still alive.
1471
1472    The gone ones will have a new *returncode* attribute indicating
1473    process exit status (may be None).
1474
1475    *callback* is a function which gets called every time a process
1476    terminates (a Process instance is passed as callback argument).
1477
1478    Function will return as soon as all processes terminate or when
1479    *timeout* occurs.
1480    Differently from Process.wait() it will not raise TimeoutExpired if
1481    *timeout* occurs.
1482
1483    Typical use case is:
1484
1485     - send SIGTERM to a list of processes
1486     - give them some time to terminate
1487     - send SIGKILL to those ones which are still alive
1488
1489    Example:
1490
1491    >>> def on_terminate(proc):
1492    ...     print("process {} terminated".format(proc))
1493    ...
1494    >>> for p in procs:
1495    ...    p.terminate()
1496    ...
1497    >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate)
1498    >>> for p in alive:
1499    ...     p.kill()
1500    """
1501    def check_gone(proc, timeout):
1502        try:
1503            returncode = proc.wait(timeout=timeout)
1504        except TimeoutExpired:
1505            pass
1506        else:
1507            if returncode is not None or not proc.is_running():
1508                proc.returncode = returncode
1509                gone.add(proc)
1510                if callback is not None:
1511                    callback(proc)
1512
1513    if timeout is not None and not timeout >= 0:
1514        msg = "timeout must be a positive integer, got %s" % timeout
1515        raise ValueError(msg)
1516    gone = set()
1517    alive = set(procs)
1518    if callback is not None and not callable(callback):
1519        raise TypeError("callback %r is not a callable" % callable)
1520    if timeout is not None:
1521        deadline = _timer() + timeout
1522
1523    while alive:
1524        if timeout is not None and timeout <= 0:
1525            break
1526        for proc in alive:
1527            # Make sure that every complete iteration (all processes)
1528            # will last max 1 sec.
1529            # We do this because we don't want to wait too long on a
1530            # single process: in case it terminates too late other
1531            # processes may disappear in the meantime and their PID
1532            # reused.
1533            max_timeout = 1.0 / len(alive)
1534            if timeout is not None:
1535                timeout = min((deadline - _timer()), max_timeout)
1536                if timeout <= 0:
1537                    break
1538                check_gone(proc, timeout)
1539            else:
1540                check_gone(proc, max_timeout)
1541        alive = alive - gone
1542
1543    if alive:
1544        # Last attempt over processes survived so far.
1545        # timeout == 0 won't make this function wait any further.
1546        for proc in alive:
1547            check_gone(proc, 0)
1548        alive = alive - gone
1549
1550    return (list(gone), list(alive))
1551
1552
1553# =====================================================================
1554# --- CPU related functions
1555# =====================================================================
1556
1557
1558def cpu_count(logical=True):
1559    """Return the number of logical CPUs in the system (same as
1560    os.cpu_count() in Python 3.4).
1561
1562    If *logical* is False return the number of physical cores only
1563    (e.g. hyper thread CPUs are excluded).
1564
1565    Return None if undetermined.
1566
1567    The return value is cached after first call.
1568    If desired cache can be cleared like this:
1569
1570    >>> psutil.cpu_count.cache_clear()
1571    """
1572    if logical:
1573        ret = _psplatform.cpu_count_logical()
1574    else:
1575        ret = _psplatform.cpu_count_physical()
1576    if ret is not None and ret < 1:
1577        ret = None
1578    return ret
1579
1580
1581def cpu_times(percpu=False):
1582    """Return system-wide CPU times as a namedtuple.
1583    Every CPU time represents the seconds the CPU has spent in the
1584    given mode. The namedtuple's fields availability varies depending on the
1585    platform:
1586
1587     - user
1588     - system
1589     - idle
1590     - nice (UNIX)
1591     - iowait (Linux)
1592     - irq (Linux, FreeBSD)
1593     - softirq (Linux)
1594     - steal (Linux >= 2.6.11)
1595     - guest (Linux >= 2.6.24)
1596     - guest_nice (Linux >= 3.2.0)
1597
1598    When *percpu* is True return a list of namedtuples for each CPU.
1599    First element of the list refers to first CPU, second element
1600    to second CPU and so on.
1601    The order of the list is consistent across calls.
1602    """
1603    if not percpu:
1604        return _psplatform.cpu_times()
1605    else:
1606        return _psplatform.per_cpu_times()
1607
1608
1609try:
1610    _last_cpu_times = cpu_times()
1611except Exception:
1612    # Don't want to crash at import time.
1613    _last_cpu_times = None
1614    traceback.print_exc()
1615
1616try:
1617    _last_per_cpu_times = cpu_times(percpu=True)
1618except Exception:
1619    # Don't want to crash at import time.
1620    _last_per_cpu_times = None
1621    traceback.print_exc()
1622
1623
1624def _cpu_tot_time(times):
1625    """Given a cpu_time() ntuple calculates the total CPU time
1626    (including idle time).
1627    """
1628    tot = sum(times)
1629    if LINUX:
1630        # On Linux guest times are already accounted in "user" or
1631        # "nice" times, so we subtract them from total.
1632        # Htop does the same. References:
1633        # https://github.com/giampaolo/psutil/pull/940
1634        # http://unix.stackexchange.com/questions/178045
1635        # https://github.com/torvalds/linux/blob/
1636        #     447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/
1637        #     cputime.c#L158
1638        tot -= getattr(times, "guest", 0)  # Linux 2.6.24+
1639        tot -= getattr(times, "guest_nice", 0)  # Linux 3.2.0+
1640    return tot
1641
1642
1643def _cpu_busy_time(times):
1644    """Given a cpu_time() ntuple calculates the busy CPU time.
1645    We do so by subtracting all idle CPU times.
1646    """
1647    busy = _cpu_tot_time(times)
1648    busy -= times.idle
1649    # Linux: "iowait" is time during which the CPU does not do anything
1650    # (waits for IO to complete). On Linux IO wait is *not* accounted
1651    # in "idle" time so we subtract it. Htop does the same.
1652    # References:
1653    # https://github.com/torvalds/linux/blob/
1654    #     447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244
1655    busy -= getattr(times, "iowait", 0)
1656    return busy
1657
1658
1659def cpu_percent(interval=None, percpu=False):
1660    """Return a float representing the current system-wide CPU
1661    utilization as a percentage.
1662
1663    When *interval* is > 0.0 compares system CPU times elapsed before
1664    and after the interval (blocking).
1665
1666    When *interval* is 0.0 or None compares system CPU times elapsed
1667    since last call or module import, returning immediately (non
1668    blocking). That means the first time this is called it will
1669    return a meaningless 0.0 value which you should ignore.
1670    In this case is recommended for accuracy that this function be
1671    called with at least 0.1 seconds between calls.
1672
1673    When *percpu* is True returns a list of floats representing the
1674    utilization as a percentage for each CPU.
1675    First element of the list refers to first CPU, second element
1676    to second CPU and so on.
1677    The order of the list is consistent across calls.
1678
1679    Examples:
1680
1681      >>> # blocking, system-wide
1682      >>> psutil.cpu_percent(interval=1)
1683      2.0
1684      >>>
1685      >>> # blocking, per-cpu
1686      >>> psutil.cpu_percent(interval=1, percpu=True)
1687      [2.0, 1.0]
1688      >>>
1689      >>> # non-blocking (percentage since last call)
1690      >>> psutil.cpu_percent(interval=None)
1691      2.9
1692      >>>
1693    """
1694    global _last_cpu_times
1695    global _last_per_cpu_times
1696    blocking = interval is not None and interval > 0.0
1697    if interval is not None and interval < 0:
1698        raise ValueError("interval is not positive (got %r)" % interval)
1699
1700    def calculate(t1, t2):
1701        t1_all = _cpu_tot_time(t1)
1702        t1_busy = _cpu_busy_time(t1)
1703
1704        t2_all = _cpu_tot_time(t2)
1705        t2_busy = _cpu_busy_time(t2)
1706
1707        # this usually indicates a float precision issue
1708        if t2_busy <= t1_busy:
1709            return 0.0
1710
1711        busy_delta = t2_busy - t1_busy
1712        all_delta = t2_all - t1_all
1713        try:
1714            busy_perc = (busy_delta / all_delta) * 100
1715        except ZeroDivisionError:
1716            return 0.0
1717        else:
1718            return round(busy_perc, 1)
1719
1720    # system-wide usage
1721    if not percpu:
1722        if blocking:
1723            t1 = cpu_times()
1724            time.sleep(interval)
1725        else:
1726            t1 = _last_cpu_times
1727            if t1 is None:
1728                # Something bad happened at import time. We'll
1729                # get a meaningful result on the next call. See:
1730                # https://github.com/giampaolo/psutil/pull/715
1731                t1 = cpu_times()
1732        _last_cpu_times = cpu_times()
1733        return calculate(t1, _last_cpu_times)
1734    # per-cpu usage
1735    else:
1736        ret = []
1737        if blocking:
1738            tot1 = cpu_times(percpu=True)
1739            time.sleep(interval)
1740        else:
1741            tot1 = _last_per_cpu_times
1742            if tot1 is None:
1743                # Something bad happened at import time. We'll
1744                # get a meaningful result on the next call. See:
1745                # https://github.com/giampaolo/psutil/pull/715
1746                tot1 = cpu_times(percpu=True)
1747        _last_per_cpu_times = cpu_times(percpu=True)
1748        for t1, t2 in zip(tot1, _last_per_cpu_times):
1749            ret.append(calculate(t1, t2))
1750        return ret
1751
1752
1753# Use separate global vars for cpu_times_percent() so that it's
1754# independent from cpu_percent() and they can both be used within
1755# the same program.
1756_last_cpu_times_2 = _last_cpu_times
1757_last_per_cpu_times_2 = _last_per_cpu_times
1758
1759
1760def cpu_times_percent(interval=None, percpu=False):
1761    """Same as cpu_percent() but provides utilization percentages
1762    for each specific CPU time as is returned by cpu_times().
1763    For instance, on Linux we'll get:
1764
1765      >>> cpu_times_percent()
1766      cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0,
1767                 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
1768      >>>
1769
1770    *interval* and *percpu* arguments have the same meaning as in
1771    cpu_percent().
1772    """
1773    global _last_cpu_times_2
1774    global _last_per_cpu_times_2
1775    blocking = interval is not None and interval > 0.0
1776    if interval is not None and interval < 0:
1777        raise ValueError("interval is not positive (got %r)" % interval)
1778
1779    def calculate(t1, t2):
1780        nums = []
1781        all_delta = _cpu_tot_time(t2) - _cpu_tot_time(t1)
1782        for field in t1._fields:
1783            field_delta = getattr(t2, field) - getattr(t1, field)
1784            try:
1785                field_perc = (100 * field_delta) / all_delta
1786            except ZeroDivisionError:
1787                field_perc = 0.0
1788            field_perc = round(field_perc, 1)
1789            # CPU times are always supposed to increase over time
1790            # or at least remain the same and that's because time
1791            # cannot go backwards.
1792            # Surprisingly sometimes this might not be the case (at
1793            # least on Windows and Linux), see:
1794            # https://github.com/giampaolo/psutil/issues/392
1795            # https://github.com/giampaolo/psutil/issues/645
1796            # I really don't know what to do about that except
1797            # forcing the value to 0 or 100.
1798            if field_perc > 100.0:
1799                field_perc = 100.0
1800            # `<=` because `-0.0 == 0.0` evaluates to True
1801            elif field_perc <= 0.0:
1802                field_perc = 0.0
1803            nums.append(field_perc)
1804        return _psplatform.scputimes(*nums)
1805
1806    # system-wide usage
1807    if not percpu:
1808        if blocking:
1809            t1 = cpu_times()
1810            time.sleep(interval)
1811        else:
1812            t1 = _last_cpu_times_2
1813            if t1 is None:
1814                # Something bad happened at import time. We'll
1815                # get a meaningful result on the next call. See:
1816                # https://github.com/giampaolo/psutil/pull/715
1817                t1 = cpu_times()
1818        _last_cpu_times_2 = cpu_times()
1819        return calculate(t1, _last_cpu_times_2)
1820    # per-cpu usage
1821    else:
1822        ret = []
1823        if blocking:
1824            tot1 = cpu_times(percpu=True)
1825            time.sleep(interval)
1826        else:
1827            tot1 = _last_per_cpu_times_2
1828            if tot1 is None:
1829                # Something bad happened at import time. We'll
1830                # get a meaningful result on the next call. See:
1831                # https://github.com/giampaolo/psutil/pull/715
1832                tot1 = cpu_times(percpu=True)
1833        _last_per_cpu_times_2 = cpu_times(percpu=True)
1834        for t1, t2 in zip(tot1, _last_per_cpu_times_2):
1835            ret.append(calculate(t1, t2))
1836        return ret
1837
1838
1839def cpu_stats():
1840    """Return CPU statistics."""
1841    return _psplatform.cpu_stats()
1842
1843
1844if hasattr(_psplatform, "cpu_freq"):
1845
1846    def cpu_freq(percpu=False):
1847        """Return CPU frequency as a nameduple including current,
1848        min and max frequency expressed in Mhz.
1849
1850        If *percpu* is True and the system supports per-cpu frequency
1851        retrieval (Linux only) a list of frequencies is returned for
1852        each CPU. If not a list with one element is returned.
1853        """
1854        ret = _psplatform.cpu_freq()
1855        if percpu:
1856            return ret
1857        else:
1858            num_cpus = float(len(ret))
1859            if num_cpus == 0:
1860                return None
1861            elif num_cpus == 1:
1862                return ret[0]
1863            else:
1864                currs, mins, maxs = 0.0, 0.0, 0.0
1865                for cpu in ret:
1866                    currs += cpu.current
1867                    mins += cpu.min
1868                    maxs += cpu.max
1869                current = currs / num_cpus
1870                min_ = mins / num_cpus
1871                max_ = maxs / num_cpus
1872                return _common.scpufreq(current, min_, max_)
1873
1874    __all__.append("cpu_freq")
1875
1876
1877# =====================================================================
1878# --- system memory related functions
1879# =====================================================================
1880
1881
1882def virtual_memory():
1883    """Return statistics about system memory usage as a namedtuple
1884    including the following fields, expressed in bytes:
1885
1886     - total:
1887       total physical memory available.
1888
1889     - available:
1890       the memory that can be given instantly to processes without the
1891       system going into swap.
1892       This is calculated by summing different memory values depending
1893       on the platform and it is supposed to be used to monitor actual
1894       memory usage in a cross platform fashion.
1895
1896     - percent:
1897       the percentage usage calculated as (total - available) / total * 100
1898
1899     - used:
1900        memory used, calculated differently depending on the platform and
1901        designed for informational purposes only:
1902        OSX: active + inactive + wired
1903        BSD: active + wired + cached
1904        LINUX: total - free
1905
1906     - free:
1907       memory not being used at all (zeroed) that is readily available;
1908       note that this doesn't reflect the actual memory available
1909       (use 'available' instead)
1910
1911    Platform-specific fields:
1912
1913     - active (UNIX):
1914       memory currently in use or very recently used, and so it is in RAM.
1915
1916     - inactive (UNIX):
1917       memory that is marked as not used.
1918
1919     - buffers (BSD, Linux):
1920       cache for things like file system metadata.
1921
1922     - cached (BSD, OSX):
1923       cache for various things.
1924
1925     - wired (OSX, BSD):
1926       memory that is marked to always stay in RAM. It is never moved to disk.
1927
1928     - shared (BSD):
1929       memory that may be simultaneously accessed by multiple processes.
1930
1931    The sum of 'used' and 'available' does not necessarily equal total.
1932    On Windows 'available' and 'free' are the same.
1933    """
1934    global _TOTAL_PHYMEM
1935    ret = _psplatform.virtual_memory()
1936    # cached for later use in Process.memory_percent()
1937    _TOTAL_PHYMEM = ret.total
1938    return ret
1939
1940
1941def swap_memory():
1942    """Return system swap memory statistics as a namedtuple including
1943    the following fields:
1944
1945     - total:   total swap memory in bytes
1946     - used:    used swap memory in bytes
1947     - free:    free swap memory in bytes
1948     - percent: the percentage usage
1949     - sin:     no. of bytes the system has swapped in from disk (cumulative)
1950     - sout:    no. of bytes the system has swapped out from disk (cumulative)
1951
1952    'sin' and 'sout' on Windows are meaningless and always set to 0.
1953    """
1954    return _psplatform.swap_memory()
1955
1956
1957# =====================================================================
1958# --- disks/paritions related functions
1959# =====================================================================
1960
1961
1962def disk_usage(path):
1963    """Return disk usage statistics about the given *path* as a
1964    namedtuple including total, used and free space expressed in bytes
1965    plus the percentage usage.
1966    """
1967    return _psplatform.disk_usage(path)
1968
1969
1970def disk_partitions(all=False):
1971    """Return mounted partitions as a list of
1972    (device, mountpoint, fstype, opts) namedtuple.
1973    'opts' field is a raw string separated by commas indicating mount
1974    options which may vary depending on the platform.
1975
1976    If *all* parameter is False return physical devices only and ignore
1977    all others.
1978    """
1979    return _psplatform.disk_partitions(all)
1980
1981
1982def disk_io_counters(perdisk=False, nowrap=True):
1983    """Return system disk I/O statistics as a namedtuple including
1984    the following fields:
1985
1986     - read_count:  number of reads
1987     - write_count: number of writes
1988     - read_bytes:  number of bytes read
1989     - write_bytes: number of bytes written
1990     - read_time:   time spent reading from disk (in ms)
1991     - write_time:  time spent writing to disk (in ms)
1992
1993    Platform specific:
1994
1995     - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms)
1996     - read_merged_count (Linux): number of merged reads
1997     - write_merged_count (Linux): number of merged writes
1998
1999    If *perdisk* is True return the same information for every
2000    physical disk installed on the system as a dictionary
2001    with partition names as the keys and the namedtuple
2002    described above as the values.
2003
2004    If *nowrap* is True it detects and adjust the numbers which overflow
2005    and wrap (restart from 0) and add "old value" to "new value" so that
2006    the returned numbers will always be increasing or remain the same,
2007    but never decrease.
2008    "disk_io_counters.cache_clear()" can be used to invalidate the
2009    cache.
2010
2011    On recent Windows versions 'diskperf -y' command may need to be
2012    executed first otherwise this function won't find any disk.
2013    """
2014    rawdict = _psplatform.disk_io_counters()
2015    if not rawdict:
2016        return {} if perdisk else None
2017    if nowrap:
2018        rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters')
2019    nt = getattr(_psplatform, "sdiskio", _common.sdiskio)
2020    if perdisk:
2021        for disk, fields in rawdict.items():
2022            rawdict[disk] = nt(*fields)
2023        return rawdict
2024    else:
2025        return nt(*[sum(x) for x in zip(*rawdict.values())])
2026
2027
2028disk_io_counters.cache_clear = functools.partial(
2029    _wrap_numbers.cache_clear, 'psutil.disk_io_counters')
2030disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache"
2031
2032
2033# =====================================================================
2034# --- network related functions
2035# =====================================================================
2036
2037
2038def net_io_counters(pernic=False, nowrap=True):
2039    """Return network I/O statistics as a namedtuple including
2040    the following fields:
2041
2042     - bytes_sent:   number of bytes sent
2043     - bytes_recv:   number of bytes received
2044     - packets_sent: number of packets sent
2045     - packets_recv: number of packets received
2046     - errin:        total number of errors while receiving
2047     - errout:       total number of errors while sending
2048     - dropin:       total number of incoming packets which were dropped
2049     - dropout:      total number of outgoing packets which were dropped
2050                     (always 0 on OSX and BSD)
2051
2052    If *pernic* is True return the same information for every
2053    network interface installed on the system as a dictionary
2054    with network interface names as the keys and the namedtuple
2055    described above as the values.
2056
2057    If *nowrap* is True it detects and adjust the numbers which overflow
2058    and wrap (restart from 0) and add "old value" to "new value" so that
2059    the returned numbers will always be increasing or remain the same,
2060    but never decrease.
2061    "disk_io_counters.cache_clear()" can be used to invalidate the
2062    cache.
2063    """
2064    rawdict = _psplatform.net_io_counters()
2065    if not rawdict:
2066        return {} if pernic else None
2067    if nowrap:
2068        rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters')
2069    if pernic:
2070        for nic, fields in rawdict.items():
2071            rawdict[nic] = _common.snetio(*fields)
2072        return rawdict
2073    else:
2074        return _common.snetio(*[sum(x) for x in zip(*rawdict.values())])
2075
2076
2077net_io_counters.cache_clear = functools.partial(
2078    _wrap_numbers.cache_clear, 'psutil.net_io_counters')
2079net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache"
2080
2081
2082def net_connections(kind='inet'):
2083    """Return system-wide socket connections as a list of
2084    (fd, family, type, laddr, raddr, status, pid) namedtuples.
2085    In case of limited privileges 'fd' and 'pid' may be set to -1
2086    and None respectively.
2087    The *kind* parameter filters for connections that fit the
2088    following criteria:
2089
2090    +------------+----------------------------------------------------+
2091    | Kind Value | Connections using                                  |
2092    +------------+----------------------------------------------------+
2093    | inet       | IPv4 and IPv6                                      |
2094    | inet4      | IPv4                                               |
2095    | inet6      | IPv6                                               |
2096    | tcp        | TCP                                                |
2097    | tcp4       | TCP over IPv4                                      |
2098    | tcp6       | TCP over IPv6                                      |
2099    | udp        | UDP                                                |
2100    | udp4       | UDP over IPv4                                      |
2101    | udp6       | UDP over IPv6                                      |
2102    | unix       | UNIX socket (both UDP and TCP protocols)           |
2103    | all        | the sum of all the possible families and protocols |
2104    +------------+----------------------------------------------------+
2105
2106    On OSX this function requires root privileges.
2107    """
2108    return _psplatform.net_connections(kind)
2109
2110
2111def net_if_addrs():
2112    """Return the addresses associated to each NIC (network interface
2113    card) installed on the system as a dictionary whose keys are the
2114    NIC names and value is a list of namedtuples for each address
2115    assigned to the NIC. Each namedtuple includes 5 fields:
2116
2117     - family: can be either socket.AF_INET, socket.AF_INET6 or
2118               psutil.AF_LINK, which refers to a MAC address.
2119     - address: is the primary address and it is always set.
2120     - netmask: and 'broadcast' and 'ptp' may be None.
2121     - ptp: stands for "point to point" and references the
2122            destination address on a point to point interface
2123            (typically a VPN).
2124     - broadcast: and *ptp* are mutually exclusive.
2125
2126    Note: you can have more than one address of the same family
2127    associated with each interface.
2128    """
2129    has_enums = sys.version_info >= (3, 4)
2130    if has_enums:
2131        import socket
2132    rawlist = _psplatform.net_if_addrs()
2133    rawlist.sort(key=lambda x: x[1])  # sort by family
2134    ret = collections.defaultdict(list)
2135    for name, fam, addr, mask, broadcast, ptp in rawlist:
2136        if has_enums:
2137            try:
2138                fam = socket.AddressFamily(fam)
2139            except ValueError:
2140                if WINDOWS and fam == -1:
2141                    fam = _psplatform.AF_LINK
2142                elif (hasattr(_psplatform, "AF_LINK") and
2143                        _psplatform.AF_LINK == fam):
2144                    # Linux defines AF_LINK as an alias for AF_PACKET.
2145                    # We re-set the family here so that repr(family)
2146                    # will show AF_LINK rather than AF_PACKET
2147                    fam = _psplatform.AF_LINK
2148        if fam == _psplatform.AF_LINK:
2149            # The underlying C function may return an incomplete MAC
2150            # address in which case we fill it with null bytes, see:
2151            # https://github.com/giampaolo/psutil/issues/786
2152            separator = ":" if POSIX else "-"
2153            while addr.count(separator) < 5:
2154                addr += "%s00" % separator
2155        ret[name].append(_common.snic(fam, addr, mask, broadcast, ptp))
2156    return dict(ret)
2157
2158
2159def net_if_stats():
2160    """Return information about each NIC (network interface card)
2161    installed on the system as a dictionary whose keys are the
2162    NIC names and value is a namedtuple with the following fields:
2163
2164     - isup: whether the interface is up (bool)
2165     - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or
2166               NIC_DUPLEX_UNKNOWN
2167     - speed: the NIC speed expressed in mega bits (MB); if it can't
2168              be determined (e.g. 'localhost') it will be set to 0.
2169     - mtu: the maximum transmission unit expressed in bytes.
2170    """
2171    return _psplatform.net_if_stats()
2172
2173
2174# =====================================================================
2175# --- sensors
2176# =====================================================================
2177
2178
2179# Linux
2180if hasattr(_psplatform, "sensors_temperatures"):
2181
2182    def sensors_temperatures(fahrenheit=False):
2183        """Return hardware temperatures. Each entry is a namedtuple
2184        representing a certain hardware sensor (it may be a CPU, an
2185        hard disk or something else, depending on the OS and its
2186        configuration).
2187        All temperatures are expressed in celsius unless *fahrenheit*
2188        is set to True.
2189        """
2190        def convert(n):
2191            if n is not None:
2192                return (float(n) * 9 / 5) + 32 if fahrenheit else n
2193
2194        ret = collections.defaultdict(list)
2195        rawdict = _psplatform.sensors_temperatures()
2196
2197        for name, values in rawdict.items():
2198            while values:
2199                label, current, high, critical = values.pop(0)
2200                current = convert(current)
2201                high = convert(high)
2202                critical = convert(critical)
2203
2204                if high and not critical:
2205                    critical = high
2206                elif critical and not high:
2207                    high = critical
2208
2209                ret[name].append(
2210                    _common.shwtemp(label, current, high, critical))
2211
2212        return dict(ret)
2213
2214    __all__.append("sensors_temperatures")
2215
2216
2217# Linux
2218if hasattr(_psplatform, "sensors_fans"):
2219
2220    def sensors_fans():
2221        """Return fans speed. Each entry is a namedtuple
2222        representing a certain hardware sensor.
2223        All speed are expressed in RPM (rounds per minute).
2224        """
2225        return _psplatform.sensors_fans()
2226
2227    __all__.append("sensors_fans")
2228
2229
2230# Linux, Windows, FreeBSD, OSX
2231if hasattr(_psplatform, "sensors_battery"):
2232
2233    def sensors_battery():
2234        """Return battery information. If no battery is installed
2235        returns None.
2236
2237         - percent: battery power left as a percentage.
2238         - secsleft: a rough approximation of how many seconds are left
2239                     before the battery runs out of power. May be
2240                     POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED.
2241         - power_plugged: True if the AC power cable is connected.
2242        """
2243        return _psplatform.sensors_battery()
2244
2245    __all__.append("sensors_battery")
2246
2247
2248# =====================================================================
2249# --- other system related functions
2250# =====================================================================
2251
2252
2253def boot_time():
2254    """Return the system boot time expressed in seconds since the epoch."""
2255    # Note: we are not caching this because it is subject to
2256    # system clock updates.
2257    return _psplatform.boot_time()
2258
2259
2260def users():
2261    """Return users currently connected on the system as a list of
2262    namedtuples including the following fields.
2263
2264     - user: the name of the user
2265     - terminal: the tty or pseudo-tty associated with the user, if any.
2266     - host: the host name associated with the entry, if any.
2267     - started: the creation time as a floating point number expressed in
2268       seconds since the epoch.
2269    """
2270    return _psplatform.users()
2271
2272
2273# =====================================================================
2274# --- Windows services
2275# =====================================================================
2276
2277
2278if WINDOWS:
2279
2280    def win_service_iter():
2281        """Return a generator yielding a WindowsService instance for all
2282        Windows services installed.
2283        """
2284        return _psplatform.win_service_iter()
2285
2286    def win_service_get(name):
2287        """Get a Windows service by *name*.
2288        Raise NoSuchProcess if no service with such name exists.
2289        """
2290        return _psplatform.win_service_get(name)
2291
2292
2293# =====================================================================
2294
2295
2296def test():  # pragma: no cover
2297    """List info of all currently running processes emulating ps aux
2298    output.
2299    """
2300    today_day = datetime.date.today()
2301    templ = "%-10s %5s %4s %7s %7s %-13s %5s %7s  %s"
2302    attrs = ['pid', 'memory_percent', 'name', 'cpu_times', 'create_time',
2303             'memory_info']
2304    if POSIX:
2305        attrs.append('uids')
2306        attrs.append('terminal')
2307    print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "TTY", "START", "TIME",
2308                   "COMMAND"))
2309    for p in process_iter(attrs=attrs, ad_value=''):
2310        if p.info['create_time']:
2311            ctime = datetime.datetime.fromtimestamp(p.info['create_time'])
2312            if ctime.date() == today_day:
2313                ctime = ctime.strftime("%H:%M")
2314            else:
2315                ctime = ctime.strftime("%b%d")
2316        else:
2317            ctime = ''
2318        cputime = time.strftime("%M:%S",
2319                                time.localtime(sum(p.info['cpu_times'])))
2320        try:
2321            user = p.username()
2322        except Error:
2323            user = ''
2324        if WINDOWS and '\\' in user:
2325            user = user.split('\\')[1]
2326        vms = p.info['memory_info'] and \
2327            int(p.info['memory_info'].vms / 1024) or '?'
2328        rss = p.info['memory_info'] and \
2329            int(p.info['memory_info'].rss / 1024) or '?'
2330        memp = p.info['memory_percent'] and \
2331            round(p.info['memory_percent'], 1) or '?'
2332        print(templ % (
2333            user[:10],
2334            p.info['pid'],
2335            memp,
2336            vms,
2337            rss,
2338            p.info.get('terminal', '') or '?',
2339            ctime,
2340            cputime,
2341            p.info['name'].strip() or '?'))
2342
2343
2344del memoize, memoize_when_activated, division, deprecated_method
2345if sys.version_info[0] < 3:
2346    del num, x
2347
2348if __name__ == "__main__":
2349    test()
2350