~ubuntu-branches/ubuntu/precise/python-psutil/precise

« back to all changes in this revision

Viewing changes to psutil/__init__.py

  • Committer: Bazaar Package Importer
  • Author(s): Sandro Tosi
  • Date: 2011-04-04 20:26:42 UTC
  • mfrom: (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110404202642-u2fyar19eabqb2mn
Tags: 0.2.1-1
* New upstream release
* debian/copyright
  - extended packaging copyright years
* debian/rules
  - use the correct PYTHONPATH when running tests, for all supported versions
* debian/control
  - it now contains also extensions, so it's an arch:any package
  - move python-support from b-d-i to b-d
  - we now need python-all-dev in b-d
  - added procps to b-d, needed to run tests
* debian/{control, pyversion}
  - removed pyversion, replaced by XS-P-V field

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
2
#
3
 
# $Id: __init__.py 531 2010-03-02 20:54:22Z billiejoex $
 
3
# $Id: __init__.py 954 2011-03-20 20:42:26Z g.rodola $
4
4
#
5
5
 
6
6
"""psutil is a module providing convenience functions for managing
7
7
processes in a portable way by using Python.
8
8
"""
9
9
 
 
10
__version__ = "0.2.1"
 
11
version_info = tuple([int(num) for num in __version__.split('.')])
 
12
 
10
13
__all__ = [
11
 
    "NoSuchProcess",
12
 
    "AccessDenied",
13
 
    "NUM_CPUS",
14
 
    "ProcessInfo",
15
 
    "Process",
16
 
    "test",
17
 
    "CPUTimes",
18
 
    "pid_exists",
19
 
    "get_pid_list",
20
 
    "process_iter",
21
 
    "get_process_list",
22
 
    "TOTAL_PHYMEM",
23
 
    "avail_phymem",
24
 
    "used_phymem",
25
 
    "total_virtmem",
26
 
    "avail_virtmem",
27
 
    "used_virtmem",
28
 
    "cpu_times",
29
 
    "cpu_percent",
 
14
    # exceptions
 
15
    "Error", "NoSuchProcess", "AccessDenied", "TimeoutExpired",
 
16
    # constants
 
17
    "NUM_CPUS", "TOTAL_PHYMEM", "BOOT_TIME",
 
18
    "version_info", "__version__",
 
19
    "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
 
20
    "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
 
21
    "STATUS_WAKING", "STATUS_LOCKED",
 
22
    # classes
 
23
    "Process", "Popen",
 
24
    # functions
 
25
    "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list",
 
26
    "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem",
 
27
    "used_virtmem", "cpu_times", "cpu_percent",
30
28
    ]
31
29
 
32
 
__version__ = '0.1.3'
33
 
 
34
 
 
35
30
import sys
36
31
import os
37
32
import time
 
33
import signal
 
34
import warnings
 
35
import errno
 
36
import subprocess
38
37
try:
39
 
    import pwd, grp
 
38
    import pwd
40
39
except ImportError:
41
 
    pwd = grp = None
 
40
    pwd = None
42
41
 
43
 
# exceptions are imported here, but may be overriden by platform
44
 
# module implementation later
45
 
from error import *
 
42
from psutil.error import Error, NoSuchProcess, AccessDenied, TimeoutExpired
 
43
from psutil._compat import property
 
44
from psutil._common import (STATUS_RUNNING, STATUS_IDLE, STATUS_SLEEPING,
 
45
                            STATUS_DISK_SLEEP, STATUS_STOPPED,
 
46
                            STATUS_TRACING_STOP, STATUS_ZOMBIE, STATUS_DEAD,
 
47
                            STATUS_WAKING, STATUS_LOCKED)
46
48
 
47
49
# import the appropriate module for our platform only
48
50
if sys.platform.lower().startswith("linux"):
49
 
    from _pslinux import *
 
51
    from psutil._pslinux import *
 
52
    __all__.extend(["cached_phymem", "phymem_buffers"])
50
53
 
51
54
elif sys.platform.lower().startswith("win32"):
52
 
    from _psmswindows import *
53
 
    __all__.append("wmi")
 
55
    from psutil._psmswindows import *
 
56
    __all__.extend(["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
 
57
                    "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",
 
58
                    "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS"])
54
59
 
55
60
elif sys.platform.lower().startswith("darwin"):
56
 
    from _psosx import *
 
61
    from psutil._psosx import *
57
62
 
58
63
elif sys.platform.lower().startswith("freebsd"):
59
 
    from _psbsd import *
 
64
    from psutil._psbsd import *
 
65
 
60
66
else:
61
 
    raise ImportError('no os specific module found')
62
 
 
63
 
# platform-specific modules define an Impl implementation class
64
 
_platform_impl = Impl()
65
 
 
66
 
 
67
 
class CPUTimes:
68
 
    """This class contains information about CPU times.
69
 
    It is not used directly but it's returned as an instance by
70
 
    psutil.cpu_times() function.
71
 
 
72
 
    Every CPU time is accessible in form of an attribute and represents
73
 
    the time CPU has spent in the given mode.
74
 
 
75
 
    The attributes availability varies depending on the platform.
76
 
    Here follows a list of all available attributes:
77
 
 
78
 
     - user
79
 
     - system
80
 
     - idle
81
 
     - nice (UNIX)
82
 
     - iowait (Linux)
83
 
     - irq (Linux, FreeBSD)
84
 
     - softirq (Linux)
85
 
    """
86
 
 
87
 
    def __init__(self, **kwargs):
88
 
        self.__attrs = []
89
 
        for name in kwargs:
90
 
            setattr(self, name, kwargs[name])
91
 
            self.__attrs.append(name)
92
 
 
93
 
    def __str__(self):
94
 
        string = []
95
 
        for attr in self.__attrs:
96
 
            value = getattr(self, attr)
97
 
            string.append("%s=%s" %(attr, value))
98
 
        return '; '.join(string)
99
 
 
100
 
    def __iter__(self):
101
 
        for attr in self.__attrs:
102
 
            yield getattr(self, attr)
103
 
 
104
 
 
105
 
class ProcessInfo(object):
106
 
    """Class that allows the process information to be passed between
107
 
    external code and psutil.  Used directly by the Process class.
108
 
    """
109
 
 
110
 
    def __init__(self, pid, ppid=None, name=None, path=None, cmdline=None,
111
 
                       uid=None, gid=None):
112
 
        self.pid = pid
113
 
        self.ppid = ppid
114
 
        self.name = name
115
 
        self.path = path
116
 
        self.cmdline = cmdline
117
 
        # if we have the cmdline but not the path, figure it out from argv[0]
118
 
        if cmdline and not path:
119
 
            self.path = os.path.dirname(cmdline[0])
120
 
        self.uid = uid
121
 
        self.gid = gid
122
 
        self.create = None
123
 
        self.username = None
 
67
    raise NotImplementedError('platform %s is not supported' % sys.platform)
124
68
 
125
69
 
126
70
class Process(object):
133
77
        if not isinstance(pid, int):
134
78
            raise ValueError("An integer is required")
135
79
        if not pid_exists(pid):
136
 
            raise NoSuchProcess("No process found with PID %s" % pid)
137
 
        self._procinfo = ProcessInfo(pid)
138
 
        self.is_proxy = True
139
 
        # try to init CPU times, if it raises AccessDenied then suppress
140
 
        # it so it won't interrupt the constructor. First call to
141
 
        # get_cpu_percent() will trigger the AccessDenied exception
142
 
        # instead.
 
80
            raise NoSuchProcess(pid, None, "no process found with PID %s" % pid)
 
81
        self._pid = pid
 
82
        # platform-specific modules define an PlatformProcess
 
83
        # implementation class
 
84
        self._platform_impl = PlatformProcess(pid)
 
85
        self._last_sys_cpu_times = None
 
86
        self._last_proc_cpu_times = None
 
87
 
 
88
    def __str__(self):
143
89
        try:
144
 
            self._last_sys_time = time.time()
145
 
            self._last_user_time, self._last_kern_time = self.get_cpu_times()
 
90
            pid = self.pid
 
91
            name = repr(self.name)
 
92
            cmdline = self.cmdline and repr(' '.join(self.cmdline))
 
93
        except NoSuchProcess:
 
94
            details = "(pid=%s (terminated))" % self.pid
146
95
        except AccessDenied:
147
 
            self._last_user_time, self._last_kern_time = None, None
 
96
            details = "(pid=%s)" % (self.pid)
 
97
        else:
 
98
            if cmdline:
 
99
                details = "(pid=%s, name=%s, cmdline=%s)" % (pid, name, cmdline)
 
100
            else:
 
101
                details = "(pid=%s, name=%s)" % (pid, name)
 
102
        return "%s.%s%s" % (self.__class__.__module__,
 
103
                            self.__class__.__name__, details)
148
104
 
149
 
    def __str__(self):
150
 
        return "psutil.Process <PID:%s; PPID:%s; NAME:'%s'; PATH:'%s'; " \
151
 
               "CMDLINE:%s; UID:%s; GID:%s;>" \
152
 
               %(self.pid, self.ppid, self.name, self.path, self.cmdline, \
153
 
                 self.uid, self.gid)
 
105
    def __repr__(self):
 
106
        return "<%s at %s>" % (self.__str__(), id(self))
154
107
 
155
108
    def __eq__(self, other):
156
 
        """Test for equality with another Process object based on PID
157
 
        and creation time."""
158
 
        # Avoid to use self.create_time directly to avoid caching in
159
 
        # case kill() gets called before create_time resulting in
160
 
        # NoSuchProcess not being raised (see issue 77):
161
 
        h1 = (self.pid, self._procinfo.create or \
162
 
                        _platform_impl.get_process_create_time(self.pid))
163
 
        h2 = (other.pid, other.create_time)
164
 
        return h1 == h2
165
 
 
166
 
    def deproxy(self):
167
 
        """Used internally by Process properties. The first call to
168
 
        deproxy() initializes the ProcessInfo object in self._procinfo
169
 
        with process data read from platform-specific module's
170
 
        get_process_info() method.
171
 
 
172
 
        This method becomes a NO-OP after the first property is accessed.
173
 
        Property data is filled in from the ProcessInfo object created,
174
 
        and further calls to deproxy() simply return immediately without
175
 
        calling get_process_info().
 
109
        """Test for equality with another Process object based on pid
 
110
        and creation time.
176
111
        """
177
 
        if self.is_proxy:
178
 
            # get_process_info returns a tuple we use as the arguments
179
 
            # to the ProcessInfo constructor
180
 
            self._procinfo = ProcessInfo(*_platform_impl.get_process_info(self._procinfo.pid))
181
 
            self.is_proxy = False
 
112
        h1 = (self.pid, self.create_time)
 
113
        try:
 
114
            h2 = (other.pid, other.create_time)
 
115
        except AttributeError:
 
116
            return False
 
117
        else:
 
118
            return h1 == h2
182
119
 
183
120
    @property
184
121
    def pid(self):
185
122
        """The process pid."""
186
 
        return self._procinfo.pid
 
123
        return self._pid
187
124
 
188
125
    @property
189
126
    def ppid(self):
190
127
        """The process parent pid."""
191
 
        self.deproxy()
192
 
        return self._procinfo.ppid
 
128
        return self._platform_impl.get_process_ppid()
193
129
 
194
130
    @property
195
131
    def parent(self):
196
 
        """Return the parent process as a Process object. If no ppid is
197
 
        known then return None."""
198
 
        if self.ppid is not None:
199
 
            return Process(self.ppid)
200
 
        return None
 
132
        """Return the parent process as a Process object. If no parent
 
133
        pid is known return None.
 
134
        """
 
135
        ppid = self.ppid
 
136
        if ppid is not None:
 
137
            try:
 
138
                return Process(ppid)
 
139
            except NoSuchProcess:
 
140
                pass
201
141
 
202
142
    @property
203
143
    def name(self):
204
144
        """The process name."""
205
 
        self.deproxy()
206
 
        return self._procinfo.name
 
145
        name = self._platform_impl.get_process_name()
 
146
        if os.name == 'posix':
 
147
            # On UNIX the name gets truncated to the first 15 characters.
 
148
            # If it matches the first part of the cmdline we return that
 
149
            # one instead because it's usually more explicative.
 
150
            # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon".
 
151
            cmdline = self.cmdline
 
152
            if cmdline:
 
153
                extended_name = os.path.basename(cmdline[0])
 
154
                if extended_name.startswith(name):
 
155
                    name = extended_name
 
156
        # XXX - perhaps needs refactoring
 
157
        self._platform_impl._process_name = name
 
158
        return name
 
159
 
 
160
    @property
 
161
    def exe(self):
 
162
        """The process executable as an absolute path name."""
 
163
        exe = self._platform_impl.get_process_exe()
 
164
        # if we have the cmdline but not the exe, figure it out from argv[0]
 
165
        if not exe:
 
166
            cmdline = self.cmdline
 
167
            if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'):
 
168
                _exe = os.path.realpath(cmdline[0])
 
169
                if os.path.isfile(_exe) and os.access(_exe, os.X_OK):
 
170
                    return _exe
 
171
        if not exe:
 
172
            raise AccessDenied(self.pid, self._platform_impl._process_name)
 
173
        return exe
207
174
 
208
175
    @property
209
176
    def path(self):
210
 
        """The process path."""
211
 
        self.deproxy()
212
 
        return self._procinfo.path
 
177
        msg = "'path' property is deprecated; use 'os.path.dirname(exe)' instead"
 
178
        warnings.warn(msg, DeprecationWarning)
 
179
        return os.path.dirname(self.exe)
213
180
 
214
181
    @property
215
182
    def cmdline(self):
216
183
        """The command line process has been called with."""
217
 
        self.deproxy()
218
 
        return self._procinfo.cmdline
 
184
        return self._platform_impl.get_process_cmdline()
 
185
 
 
186
    @property
 
187
    def status(self):
 
188
        """The process current status as a STATUS_* constant."""
 
189
        return self._platform_impl.get_process_status()
 
190
 
 
191
    @property
 
192
    def nice(self):
 
193
        """Get or set process niceness (priority)."""
 
194
        return self._platform_impl.get_process_nice()
 
195
 
 
196
    @nice.setter
 
197
    def nice(self, value):
 
198
        # invoked on "p.nice = num"; change process niceness
 
199
        return self._platform_impl.set_process_nice(value)
 
200
 
 
201
    if os.name == 'posix':
 
202
 
 
203
        @property
 
204
        def uids(self):
 
205
            """Return a named tuple denoting the process real,
 
206
            effective, and saved user ids.
 
207
            """
 
208
            return self._platform_impl.get_process_uids()
 
209
 
 
210
        @property
 
211
        def gids(self):
 
212
            """Return a named tuple denoting the process real,
 
213
            effective, and saved group ids.
 
214
            """
 
215
            return self._platform_impl.get_process_gids()
219
216
 
220
217
    @property
221
218
    def uid(self):
222
 
        """The real user id of the current process."""
223
 
        self.deproxy()
224
 
        return self._procinfo.uid
 
219
        """The real user id of the current process (deprecated)."""
 
220
        warnings.warn("'uid' property is deprecated; use 'uids.real' instead",
 
221
                      DeprecationWarning)
 
222
        if os.name != 'posix':
 
223
            return -1
 
224
        return self.uids.real
225
225
 
226
226
    @property
227
227
    def gid(self):
228
 
        """The real group id of the current process."""
229
 
        self.deproxy()
230
 
        return self._procinfo.gid
 
228
        """The real group id of the current process (deprecated)."""
 
229
        warnings.warn("'gid' property is deprecated; use 'uids.real' instead",
 
230
                      DeprecationWarning)
 
231
        if os.name != 'posix':
 
232
            return -1
 
233
        return self.gids.real
231
234
 
232
235
    @property
233
236
    def username(self):
234
 
        """The name of the user that owns the process."""
235
 
        if self._procinfo.username is not None:
236
 
            return self._procinfo.username
237
 
        if pwd is not None:
238
 
            self._procinfo.username = pwd.getpwuid(self.uid).pw_name
 
237
        """The name of the user that owns the process.
 
238
        On UNIX this is calculated by using *real* process uid.
 
239
        """
 
240
        if os.name == 'posix':
 
241
            if pwd is None:
 
242
                # might happen if python was installed from sources
 
243
                raise ImportError("requires pwd module shipped with standard python")
 
244
            return pwd.getpwuid(self.uids.real).pw_name
239
245
        else:
240
 
            self._procinfo.username =  _platform_impl.get_process_username(self.pid)
241
 
        return self._procinfo.username
 
246
            return self._platform_impl.get_process_username()
242
247
 
243
248
    @property
244
249
    def create_time(self):
245
250
        """The process creation time as a floating point number
246
251
        expressed in seconds since the epoch, in UTC.
247
252
        """
248
 
        if self._procinfo.create is None:
249
 
            self._procinfo.create = _platform_impl.get_process_create_time(self.pid)
250
 
        return self._procinfo.create
 
253
        return self._platform_impl.get_process_create_time()
251
254
 
252
255
    # available for Windows and Linux only
253
 
    if hasattr(_platform_impl, "get_process_cwd"):
 
256
    if hasattr(PlatformProcess, "get_process_cwd"):
 
257
 
254
258
        def getcwd(self):
255
259
            """Return a string representing the process current working
256
260
            directory.
257
261
            """
258
 
            return _platform_impl.get_process_cwd(self.pid)
259
 
 
260
 
    def suspend(self):
261
 
        """Suspend process execution."""
262
 
        # safety measure in case the current process has been killed in
263
 
        # meantime and the kernel reused its PID
264
 
        if not self.is_running():
265
 
            raise NoSuchProcess
266
 
        # windows
267
 
        if hasattr(_platform_impl, "suspend_process"):
268
 
            _platform_impl.suspend_process(self.pid)
269
 
        else:
270
 
            # posix
271
 
            try:
272
 
                os.kill(self.pid, signal.SIGSTOP)
273
 
            except OSError, err:
274
 
                if err.errno == errno.ESRCH:
275
 
                    raise NoSuchProcess(self.pid)
276
 
                raise
277
 
 
278
 
    def resume(self):
279
 
        """Resume process execution."""
280
 
        # safety measure in case the current process has been killed in
281
 
        # meantime and the kernel reused its PID
282
 
        if not self.is_running():
283
 
            raise NoSuchProcess
284
 
        # windows
285
 
        if hasattr(_platform_impl, "resume_process"):
286
 
            _platform_impl.resume_process(self.pid)
287
 
        else:
288
 
            # posix
289
 
            try:
290
 
                os.kill(self.pid, signal.SIGCONT)
291
 
            except OSError, err:
292
 
                if err.errno == errno.ESRCH:
293
 
                    raise NoSuchProcess(self.pid)
294
 
                raise
295
 
 
296
 
    def get_cpu_percent(self):
297
 
        """Compare process times to system time elapsed since last call
298
 
        and calculate CPU utilization as a percentage. It is recommended
299
 
        for accuracy that this function be called with at least 1 second
300
 
        between calls. The initial delta is calculated from the
301
 
        instantiation of the Process object.
302
 
        """
303
 
        now = time.time()
304
 
        # will raise AccessDenied on OS X if not root or in procmod group
305
 
        user_t, kern_t = _platform_impl.get_cpu_times(self.pid)
306
 
 
307
 
        total_proc_time = float((user_t - self._last_user_time) + \
308
 
                                (kern_t - self._last_kern_time))
 
262
            return self._platform_impl.get_process_cwd()
 
263
 
 
264
    # Linux, BSD and Windows only
 
265
    if hasattr(PlatformProcess, "get_process_io_counters"):
 
266
 
 
267
        def get_io_counters(self):
 
268
            """Return process I/O statistics as a namedtuple including
 
269
            the number of read/write calls performed and the amount of
 
270
            bytes read and written by the process.
 
271
            """
 
272
            return self._platform_impl.get_process_io_counters()
 
273
 
 
274
    # available only on Linux
 
275
    if hasattr(PlatformProcess, "get_process_ionice"):
 
276
 
 
277
        def get_ionice(self):
 
278
            """Return process I/O niceness (priority) as a namedtuple."""
 
279
            return self._platform_impl.get_process_ionice()
 
280
 
 
281
        def set_ionice(self, ioclass, value=None):
 
282
            """Set process I/O niceness (priority).
 
283
            ioclass is one of the IOPRIO_CLASS_* constants.
 
284
            iodata is a number which goes from 0 to 7. The higher the
 
285
            value, the lower the I/O priority of the process.
 
286
            """
 
287
            return self._platform_impl.set_process_ionice(ioclass, value)
 
288
 
 
289
    def get_num_threads(self):
 
290
        """Return the number of threads used by this process."""
 
291
        return self._platform_impl.get_process_num_threads()
 
292
 
 
293
    def get_threads(self):
 
294
        """Return threads opened by process as a list of namedtuples
 
295
        including thread id and thread CPU times (user/system).
 
296
        """
 
297
        return self._platform_impl.get_process_threads()
 
298
 
 
299
    def get_children(self):
 
300
        """Return the children of this process as a list of Process
 
301
        objects.
 
302
        """
 
303
        if not self.is_running():
 
304
            name = self._platform_impl._process_name
 
305
            raise NoSuchProcess(self.pid, name)
 
306
        retlist = []
 
307
        for proc in process_iter():
 
308
            try:
 
309
                if proc.ppid == self.pid:
 
310
                    retlist.append(proc)
 
311
            except NoSuchProcess:
 
312
                pass
 
313
        return retlist
 
314
 
 
315
    def get_cpu_percent(self, interval=0.1):
 
316
        """Return a float representing the current process CPU
 
317
        utilization as a percentage.
 
318
 
 
319
        When interval is > 0.0 compares process times to system CPU
 
320
        times elapsed before and after the interval (blocking).
 
321
 
 
322
        When interval is 0.0 or None compares process times to system CPU
 
323
        times elapsed since last call, returning immediately.
 
324
        In this case is recommended for accuracy that this function be
 
325
        called with at least 0.1 seconds between calls.
 
326
        """
 
327
        blocking = interval is not None and interval > 0.0
 
328
        if blocking:
 
329
            st1 = sum(cpu_times())
 
330
            pt1 = self._platform_impl.get_cpu_times()
 
331
            time.sleep(interval)
 
332
            st2 = sum(cpu_times())
 
333
            pt2 = self._platform_impl.get_cpu_times()
 
334
        else:
 
335
            st1 = self._last_sys_cpu_times
 
336
            pt1 = self._last_proc_cpu_times
 
337
            st2 = sum(cpu_times())
 
338
            pt2 = self._platform_impl.get_cpu_times()
 
339
            if st1 is None or pt1 is None:
 
340
                self._last_sys_cpu_times = st2
 
341
                self._last_proc_cpu_times = pt2
 
342
                return 0.0
 
343
 
 
344
        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
 
345
        delta_time = st2 - st1
 
346
        # reset values for next call in case of interval == None
 
347
        self._last_sys_cpu_times = st2
 
348
        self._last_proc_cpu_times = pt2
 
349
 
309
350
        try:
310
 
            percent = total_proc_time / float((now - self._last_sys_time))
 
351
            # the utilization split between all CPUs
 
352
            overall_percent = (delta_proc / delta_time) * 100
311
353
        except ZeroDivisionError:
312
 
            percent = 0.000
313
 
 
314
 
        # reset the values
315
 
        self._last_sys_time = time.time()
316
 
        self._last_user_time, self._last_kern_time = self.get_cpu_times()
317
 
 
318
 
        return (percent * 100.0)
 
354
            # interval was too low
 
355
            return 0.0
 
356
        # the utilization of a single CPU
 
357
        single_cpu_percent = overall_percent * NUM_CPUS
 
358
        # ugly hack to avoid troubles with float precision issues
 
359
        if single_cpu_percent > 100.0:
 
360
            return 100.0
 
361
        return round(single_cpu_percent, 1)
319
362
 
320
363
    def get_cpu_times(self):
321
364
        """Return a tuple whose values are process CPU user and system
322
 
        time.  These are the same first two values that os.times()
323
 
        returns for the current process.
 
365
        times. The same as os.times() but per-process.
324
366
        """
325
 
        return _platform_impl.get_cpu_times(self.pid)
 
367
        return self._platform_impl.get_cpu_times()
326
368
 
327
369
    def get_memory_info(self):
328
370
        """Return a tuple representing RSS (Resident Set Size) and VMS
333
375
        On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns
334
376
        of taskmgr.exe.
335
377
        """
336
 
        return _platform_impl.get_memory_info(self.pid)
 
378
        return self._platform_impl.get_memory_info()
337
379
 
338
380
    def get_memory_percent(self):
339
381
        """Compare physical system memory to process resident memory and
340
382
        calculate process memory utilization as a percentage.
341
383
        """
342
 
        rss = _platform_impl.get_memory_info(self.pid)[0]
 
384
        rss = self._platform_impl.get_memory_info()[0]
343
385
        try:
344
386
            return (rss / float(TOTAL_PHYMEM)) * 100
345
387
        except ZeroDivisionError:
346
388
            return 0.0
347
389
 
 
390
    def get_open_files(self):
 
391
        """Return files opened by process as a list of namedtuples
 
392
        including absolute file name and file descriptor number.
 
393
        """
 
394
        return self._platform_impl.get_open_files()
 
395
 
 
396
    def get_connections(self):
 
397
        """Return TCP and UPD connections opened by process as a list
 
398
        of namedtuples.
 
399
        On BSD and OSX results for third party processes (!= os.getpid())
 
400
        can differ depending on user privileges.
 
401
        """
 
402
        return self._platform_impl.get_connections()
 
403
 
348
404
    def is_running(self):
349
 
        """Return whether the current process is running in the current process
350
 
        list."""
 
405
        """Return whether the current process is running in the current
 
406
        process list.
 
407
        """
351
408
        try:
352
409
            newproc = Process(self.pid)
353
410
            return self == newproc
354
411
        except NoSuchProcess:
355
412
            return False
356
413
 
357
 
    def kill(self, sig=None):
358
 
        """Kill the current process by using signal sig (defaults to SIGKILL).
359
 
        """
360
 
        # safety measure in case the current process has been killed in
361
 
        # meantime and the kernel reused its PID
362
 
        if not self.is_running():
363
 
            raise NoSuchProcess
364
 
        _platform_impl.kill_process(self.pid, sig)
365
 
 
366
 
 
367
 
def pid_exists(pid):
368
 
    """Check whether the given PID exists in the current process list."""
369
 
    return _platform_impl.pid_exists(pid)
370
 
 
371
 
def get_pid_list():
372
 
    """Return a list of current running PIDs."""
373
 
    return _platform_impl.get_pid_list()
 
414
    def send_signal(self, sig):
 
415
        """Send a signal to process (see signal module constants).
 
416
        On Windows only SIGTERM is valid and is treated as an alias
 
417
        for kill().
 
418
        """
 
419
        # safety measure in case the current process has been killed in
 
420
        # meantime and the kernel reused its PID
 
421
        if not self.is_running():
 
422
            name = self._platform_impl._process_name
 
423
            raise NoSuchProcess(self.pid, name)
 
424
        if os.name == 'posix':
 
425
            try:
 
426
                os.kill(self.pid, sig)
 
427
            except OSError, err:
 
428
                name = self._platform_impl._process_name
 
429
                if err.errno == errno.ESRCH:
 
430
                    raise NoSuchProcess(self.pid, name)
 
431
                if err.errno == errno.EPERM:
 
432
                    raise AccessDenied(self.pid, name)
 
433
                raise
 
434
        else:
 
435
            if sig == signal.SIGTERM:
 
436
                self._platform_impl.kill_process()
 
437
            else:
 
438
                raise ValueError("only SIGTERM is supported on Windows")
 
439
 
 
440
    def suspend(self):
 
441
        """Suspend process execution."""
 
442
        # safety measure in case the current process has been killed in
 
443
        # meantime and the kernel reused its PID
 
444
        if not self.is_running():
 
445
            name = self._platform_impl._process_name
 
446
            raise NoSuchProcess(self.pid, name)
 
447
        # windows
 
448
        if hasattr(self._platform_impl, "suspend_process"):
 
449
            self._platform_impl.suspend_process()
 
450
        else:
 
451
            # posix
 
452
            self.send_signal(signal.SIGSTOP)
 
453
 
 
454
    def resume(self):
 
455
        """Resume process execution."""
 
456
        # safety measure in case the current process has been killed in
 
457
        # meantime and the kernel reused its PID
 
458
        if not self.is_running():
 
459
            name = self._platform_impl._process_name
 
460
            raise NoSuchProcess(self.pid, name)
 
461
        # windows
 
462
        if hasattr(self._platform_impl, "resume_process"):
 
463
            self._platform_impl.resume_process()
 
464
        else:
 
465
            # posix
 
466
            self.send_signal(signal.SIGCONT)
 
467
 
 
468
    def terminate(self):
 
469
        """Terminate the process with SIGTERM.
 
470
        On Windows this is an alias for kill().
 
471
        """
 
472
        self.send_signal(signal.SIGTERM)
 
473
 
 
474
    def kill(self):
 
475
        """Kill the current process."""
 
476
        # safety measure in case the current process has been killed in
 
477
        # meantime and the kernel reused its PID
 
478
        if not self.is_running():
 
479
            name = self._platform_impl._process_name
 
480
            raise NoSuchProcess(self.pid, name)
 
481
        if os.name == 'posix':
 
482
            self.send_signal(signal.SIGKILL)
 
483
        else:
 
484
            self._platform_impl.kill_process()
 
485
 
 
486
    def wait(self, timeout=None):
 
487
        """Wait for process to terminate and, if process is a children
 
488
        of the current one also return its exit code, else None.
 
489
        """
 
490
        return self._platform_impl.process_wait(timeout)
 
491
 
 
492
 
 
493
class Popen(Process):
 
494
    """A more convenient interface to stdlib subprocess module.
 
495
    It starts a sub process and deals with it exactly as when using
 
496
    subprocess.Popen class but in addition also provides all the
 
497
    property and methods of psutil.Process class in a unique interface:
 
498
 
 
499
      >>> import psutil
 
500
      >>> from subprocess import PIPE
 
501
      >>> p = psutil.Popen(["/usr/bin/python", "-c", "print 'hi'"], stdout=PIPE)
 
502
      >>> p.name
 
503
      'python'
 
504
      >>> p.uids
 
505
      user(real=1000, effective=1000, saved=1000)
 
506
      >>> p.username
 
507
      'giampaolo'
 
508
      >>> p.communicate()
 
509
      ('hi\n', None)
 
510
      >>> p.terminate()
 
511
      >>> p.wait(timeout=2)
 
512
      0
 
513
      >>>
 
514
 
 
515
    For method names common to both classes such as kill(), terminate()
 
516
    and wait(), psutil.Process implementation takes precedence.
 
517
 
 
518
    For a complete documentation refers to:
 
519
    http://docs.python.org/library/subprocess.html
 
520
    """
 
521
 
 
522
    def __init__(self, *args, **kwargs):
 
523
        self.__subproc = subprocess.Popen(*args, **kwargs)
 
524
        Process.__init__(self, self.__subproc.pid)
 
525
 
 
526
    def __dir__(self):
 
527
        return list(set(dir(Popen) + dir(subprocess.Popen)))
 
528
 
 
529
    def __getattribute__(self, name):
 
530
        try:
 
531
            return object.__getattribute__(self, name)
 
532
        except AttributeError:
 
533
            try:
 
534
                return object.__getattribute__(self.__subproc, name)
 
535
            except AttributeError:
 
536
                raise AttributeError("%s instance has no attribute '%s'"
 
537
                                      %(self.__class__.__name__, name))
 
538
 
374
539
 
375
540
def process_iter():
376
541
    """Return an iterator yielding a Process class instances for all
377
542
    running processes on the local machine.
378
543
    """
379
 
    pids = _platform_impl.get_pid_list()
380
 
    # for each PID, create a proxyied Process object
381
 
    # it will lazy init it's name and path later if required
 
544
    pids = get_pid_list()
382
545
    for pid in pids:
383
546
        try:
384
547
            yield Process(pid)
392
555
    return list(process_iter())
393
556
 
394
557
def cpu_times():
395
 
    """Return system CPU times as a CPUTimes object."""
396
 
    values = get_system_cpu_times()
397
 
    return CPUTimes(**values)
398
 
 
399
 
_last_idle_time = cpu_times().idle
400
 
_last_time = time.time()
401
 
 
402
 
def cpu_percent():
403
 
    """Return the current system-wide CPU utilization as a percentage. For
404
 
    highest accuracy, it is recommended that this be called at least 1/10th
405
 
    of a second after importing the module or calling cpu_percent() in a
406
 
    previous call, to allow for a larger time delta from which to calculate
407
 
    the percentage value.
408
 
    """
409
 
    global _last_idle_time
410
 
    global _last_time
411
 
 
412
 
    idle_time = cpu_times().idle
413
 
    curr_time = time.time()
414
 
 
415
 
    time_delta = curr_time - _last_time
416
 
    idle_delta = idle_time - _last_idle_time
417
 
 
418
 
    # reset values for next run
419
 
    _last_idle_time = idle_time
420
 
    _last_time = curr_time
421
 
 
422
 
    # Removed; see Issue #67: http://code.google.com/p/psutil/issues/detail?id=67
423
 
    # invalid data, will not be accurate so return 0.0 to avoid an overflow
424
 
    #if time_delta < idle_delta:
425
 
    #    return 0.0
426
 
 
427
 
    try :
428
 
        idle_percent = (idle_delta / time_delta) * 100.0
429
 
        util_percent = ((100 * NUM_CPUS) - idle_percent) / NUM_CPUS
430
 
    except ZeroDivisionError:
431
 
        return 0.0
432
 
 
433
 
    if util_percent < 0:
434
 
        return 0.0
 
558
    """Return system CPU times as a namedtuple object.
 
559
    Every CPU time represents the time CPU has spent in the given mode.
 
560
    The attributes availability varies depending on the platform.
 
561
    Here follows a list of all available attributes:
 
562
     - user
 
563
     - system
 
564
     - idle
 
565
     - nice (UNIX)
 
566
     - iowait (Linux)
 
567
     - irq (Linux, FreeBSD)
 
568
     - softirq (Linux)
 
569
    """
 
570
    return get_system_cpu_times()
 
571
 
 
572
 
 
573
_last_cpu_times = cpu_times()
 
574
 
 
575
def cpu_percent(interval=0.1):
 
576
    """Return a float representing the current system-wide CPU
 
577
    utilization as a percentage.
 
578
 
 
579
    When interval is > 0.0 compares system CPU times elapsed before
 
580
    and after the interval (blocking).
 
581
 
 
582
    When interval is 0.0 or None compares system CPU times elapsed
 
583
    since last call or module import, returning immediately.
 
584
    In this case is recommended for accuracy that this function be
 
585
    called with at least 0.1 seconds between calls.
 
586
    """
 
587
    global _last_cpu_times
 
588
 
 
589
    blocking = interval is not None and interval > 0.0
 
590
    if blocking:
 
591
        t1 = cpu_times()
 
592
        time.sleep(interval)
435
593
    else:
436
 
        return util_percent
 
594
        t1 = _last_cpu_times
 
595
 
 
596
    t1_all = sum(t1)
 
597
    t1_busy = t1_all - t1.idle
 
598
 
 
599
    t2 = cpu_times()
 
600
    t2_all = sum(t2)
 
601
    t2_busy = t2_all - t2.idle
 
602
 
 
603
    _last_cpu_times = t1
 
604
    # this usually indicates a float precision issue
 
605
    if t2_busy <= t1_busy:
 
606
        return 0.0
 
607
 
 
608
    busy_delta = t2_busy - t1_busy
 
609
    all_delta = t2_all - t1_all
 
610
    busy_perc = (busy_delta / all_delta) * 100
 
611
    return round(busy_perc, 1)
437
612
 
438
613
 
439
614
def test():
449
624
        if os.name == 'nt' and '\\' in user:
450
625
            user = user.split('\\')[1]
451
626
        pid = proc.pid
452
 
        cpu = round(proc.get_cpu_percent(), 1)
 
627
        cpu = round(proc.get_cpu_percent(interval=None), 1)
453
628
        mem = round(proc.get_memory_percent(), 1)
454
629
        rss, vsz = [x / 1024 for x in proc.get_memory_info()]
455
630
 
465
640
        # where cmdline is not available UNIX shows process name between
466
641
        # [] parentheses
467
642
        if not cmd:
468
 
            cmd = "[%s]" %proc.name
 
643
            cmd = "[%s]" % proc.name
469
644
        return "%-9s %-5s %-4s %4s %7s %7s %5s %8s %s" \
470
 
               %(user, pid, cpu, mem, vsz, rss, start, cputime, cmd)
 
645
                % (user, pid, cpu, mem, vsz, rss, start, cputime, cmd)
471
646
 
472
647
    print "%-9s %-5s %-4s %4s %7s %7s %5s %7s  %s" \
473
 
       %("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "START", "TIME", "COMMAND")
 
648
      % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "START", "TIME", "COMMAND")
474
649
    pids = get_pid_list()
475
650
    pids.sort()
476
651
    for pid in pids:
483
658
 
484
659
if __name__ == "__main__":
485
660
    test()
 
661