OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # $Id: __init__.py 806 2010-11-12 23:09:35Z g.rodola $ | 3 # $Id: __init__.py 1142 2011-10-05 18:45:49Z g.rodola $ |
4 # | 4 # |
| 5 # Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. |
| 6 # Use of this source code is governed by a BSD-style license that can be |
| 7 # found in the LICENSE file. |
5 | 8 |
6 """psutil is a module providing convenience functions for managing | 9 """psutil is a module providing convenience functions for managing |
7 processes in a portable way by using Python. | 10 processes and gather system information in a portable way by using |
| 11 Python. |
8 """ | 12 """ |
9 | 13 |
10 __version__ = "0.2.0" | 14 __version__ = "0.3.1" |
11 version_info = tuple([int(num) for num in __version__.split('.')]) | 15 version_info = tuple([int(num) for num in __version__.split('.')]) |
12 | 16 |
13 __all__ = [ | 17 __all__ = [ |
14 # exceptions | 18 # exceptions |
15 "Error", "NoSuchProcess", "AccessDenied", | 19 "Error", "NoSuchProcess", "AccessDenied", "TimeoutExpired", |
16 # constants | 20 # constants |
17 "NUM_CPUS", "TOTAL_PHYMEM", "version_info", "__version__", | 21 "NUM_CPUS", "TOTAL_PHYMEM", "BOOT_TIME", |
| 22 "version_info", "__version__", |
| 23 "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", |
| 24 "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", |
| 25 "STATUS_WAKING", "STATUS_LOCKED", |
18 # classes | 26 # classes |
19 "Process", | 27 "Process", "Popen", |
20 # functions | 28 # functions |
21 "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list", | 29 "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list", |
22 "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem", | 30 "phymem_usage", "virtmem_usage" |
23 "used_virtmem", "cpu_times", "cpu_percent", | 31 "cpu_times", "per_cpu_times", "cpu_percent", "per_cpu_percent", |
| 32 "network_io_counters", "disk_io_counters", |
24 ] | 33 ] |
25 | 34 |
26 import sys | 35 import sys |
27 import os | 36 import os |
28 import time | 37 import time |
29 import signal | 38 import signal |
30 import warnings | 39 import warnings |
31 import errno | 40 import errno |
| 41 import subprocess |
32 try: | 42 try: |
33 import pwd | 43 import pwd |
34 except ImportError: | 44 except ImportError: |
35 pwd = None | 45 pwd = None |
36 | 46 |
37 from psutil.error import Error, NoSuchProcess, AccessDenied | 47 from psutil.error import Error, NoSuchProcess, AccessDenied, TimeoutExpired |
| 48 from psutil._compat import property |
| 49 from psutil._common import (STATUS_RUNNING, STATUS_IDLE, STATUS_SLEEPING, |
| 50 STATUS_DISK_SLEEP, STATUS_STOPPED, |
| 51 STATUS_TRACING_STOP, STATUS_ZOMBIE, STATUS_DEAD, |
| 52 STATUS_WAKING, STATUS_LOCKED |
| 53 ) |
38 | 54 |
39 # import the appropriate module for our platform only | 55 # import the appropriate module for our platform only |
40 if sys.platform.lower().startswith("linux"): | 56 if sys.platform.lower().startswith("linux"): |
41 from psutil._pslinux import * | 57 import psutil._pslinux as _psplatform |
42 __all__.extend(["cached_phymem", "phymem_buffers"]) | 58 from psutil._pslinux import (phymem_buffers, |
| 59 cached_phymem, |
| 60 IOPRIO_CLASS_NONE, |
| 61 IOPRIO_CLASS_RT, |
| 62 IOPRIO_CLASS_BE, |
| 63 IOPRIO_CLASS_IDLE) |
| 64 phymem_buffers = _psplatform.phymem_buffers |
| 65 cached_phymem = _psplatform.cached_phymem |
43 | 66 |
44 elif sys.platform.lower().startswith("win32"): | 67 elif sys.platform.lower().startswith("win32"): |
45 from psutil._psmswindows import * | 68 import psutil._psmswindows as _psplatform |
| 69 from psutil._psmswindows import (ABOVE_NORMAL_PRIORITY_CLASS, |
| 70 BELOW_NORMAL_PRIORITY_CLASS, |
| 71 HIGH_PRIORITY_CLASS, |
| 72 IDLE_PRIORITY_CLASS, |
| 73 NORMAL_PRIORITY_CLASS, |
| 74 REALTIME_PRIORITY_CLASS) |
46 | 75 |
47 elif sys.platform.lower().startswith("darwin"): | 76 elif sys.platform.lower().startswith("darwin"): |
48 from psutil._psosx import * | 77 import psutil._psosx as _psplatform |
49 | 78 |
50 elif sys.platform.lower().startswith("freebsd"): | 79 elif sys.platform.lower().startswith("freebsd"): |
51 from psutil._psbsd import * | 80 import psutil._psbsd as _psplatform |
52 | 81 |
53 else: | 82 else: |
54 raise NotImplementedError('platform %s is not supported' % sys.platform) | 83 raise NotImplementedError('platform %s is not supported' % sys.platform) |
55 | 84 |
| 85 __all__.extend(_psplatform.__extra__all__) |
56 | 86 |
57 class CPUTimes: | 87 NUM_CPUS = _psplatform.NUM_CPUS |
58 """This class contains information about CPU times. | 88 BOOT_TIME = _psplatform.BOOT_TIME |
59 It is not used directly but it's returned as an instance by | 89 TOTAL_PHYMEM = _psplatform.phymem_usage()[0] |
60 psutil.cpu_times() function. | |
61 | 90 |
62 Every CPU time is accessible in form of an attribute and represents | 91 get_pid_list = _psplatform.get_pid_list |
63 the time CPU has spent in the given mode. | 92 pid_exists = _psplatform.pid_exists |
64 | |
65 The attributes availability varies depending on the platform. | |
66 Here follows a list of all available attributes: | |
67 | |
68 - user | |
69 - system | |
70 - idle | |
71 - nice (UNIX) | |
72 - iowait (Linux) | |
73 - irq (Linux, FreeBSD) | |
74 - softirq (Linux) | |
75 """ | |
76 | |
77 def __init__(self, **kwargs): | |
78 self.__attrs = [] | |
79 for name in kwargs: | |
80 setattr(self, name, kwargs[name]) | |
81 self.__attrs.append(name) | |
82 | |
83 def __str__(self): | |
84 string = [] | |
85 for attr in self.__attrs: | |
86 value = getattr(self, attr) | |
87 string.append("%s=%s" %(attr, value)) | |
88 return '; '.join(string) | |
89 | |
90 def __iter__(self): | |
91 for attr in self.__attrs: | |
92 yield getattr(self, attr) | |
93 | 93 |
94 | 94 |
95 class Process(object): | 95 class Process(object): |
96 """Represents an OS process.""" | 96 """Represents an OS process.""" |
97 | 97 |
98 def __init__(self, pid): | 98 def __init__(self, pid): |
99 """Create a new Process object, raises NoSuchProcess if the PID | 99 """Create a new Process object, raises NoSuchProcess if the PID |
100 does not exist, and ValueError if the parameter is not an | 100 does not exist, and ValueError if the parameter is not an |
101 integer PID.""" | 101 integer PID. |
| 102 """ |
102 if not isinstance(pid, int): | 103 if not isinstance(pid, int): |
103 raise ValueError("An integer is required") | 104 raise ValueError("an integer is required") |
104 if not pid_exists(pid): | 105 if not pid_exists(pid): |
105 raise NoSuchProcess(pid, None, "no process found with PID %s" % pid) | 106 raise NoSuchProcess(pid, None, "no process found with pid %s" % pid) |
106 self._pid = pid | 107 self._pid = pid |
107 # platform-specific modules define an PlatformProcess | 108 # platform-specific modules define an _psplatform.Process |
108 # implementation class | 109 # implementation class |
109 self._platform_impl = PlatformProcess(pid) | 110 self._platform_impl = _psplatform.Process(pid) |
110 self._last_sys_cpu_times = None | 111 self._last_sys_cpu_times = None |
111 self._last_proc_cpu_times = None | 112 self._last_proc_cpu_times = None |
112 | 113 |
113 def __str__(self): | 114 def __str__(self): |
114 try: | 115 try: |
115 pid = self.pid | 116 pid = self.pid |
116 name = repr(self.name) | 117 name = repr(self.name) |
117 cmdline = self.cmdline and repr(' '.join(self.cmdline)) | |
118 except NoSuchProcess: | 118 except NoSuchProcess: |
119 details = "(pid=%s (terminated))" % self.pid | 119 details = "(pid=%s (terminated))" % self.pid |
120 except AccessDenied: | 120 except AccessDenied: |
121 details = "(pid=%s)" % (self.pid) | 121 details = "(pid=%s)" % (self.pid) |
122 else: | 122 else: |
123 if cmdline: | 123 details = "(pid=%s, name=%s)" % (pid, name) |
124 details = "(pid=%s, name=%s, cmdline=%s)" % (pid, name, cmdline) | 124 return "%s.%s%s" % (self.__class__.__module__, |
125 else: | 125 self.__class__.__name__, details) |
126 details = "(pid=%s, name=%s)" % (pid, name) | |
127 return "%s.%s %s" % (self.__class__.__module__, | |
128 self.__class__.__name__, details) | |
129 | 126 |
130 def __repr__(self): | 127 def __repr__(self): |
131 return "<%s at %s>" % (self.__str__(), id(self)) | 128 return "<%s at %s>" % (self.__str__(), id(self)) |
132 | 129 |
133 def __eq__(self, other): | |
134 """Test for equality with another Process object based on pid | |
135 and creation time. | |
136 """ | |
137 h1 = (self.pid, self.create_time) | |
138 h2 = (other.pid, other.create_time) | |
139 return h1 == h2 | |
140 | |
141 @property | 130 @property |
142 def pid(self): | 131 def pid(self): |
143 """The process pid.""" | 132 """The process pid.""" |
144 return self._pid | 133 return self._pid |
145 | 134 |
146 @property | 135 @property |
147 def ppid(self): | 136 def ppid(self): |
148 """The process parent pid.""" | 137 """The process parent pid.""" |
149 return self._platform_impl.get_process_ppid() | 138 return self._platform_impl.get_process_ppid() |
150 | 139 |
151 @property | 140 @property |
152 def parent(self): | 141 def parent(self): |
153 """Return the parent process as a Process object. If no ppid is | 142 """Return the parent process as a Process object. If no parent |
154 known then return None.""" | 143 pid is known return None. |
155 if self.ppid is not None: | 144 """ |
156 return Process(self.ppid) | 145 ppid = self.ppid |
157 return None | 146 if ppid is not None: |
| 147 try: |
| 148 return Process(ppid) |
| 149 except NoSuchProcess: |
| 150 pass |
158 | 151 |
159 @property | 152 @property |
160 def name(self): | 153 def name(self): |
161 """The process name.""" | 154 """The process name.""" |
162 name = self._platform_impl.get_process_name() | 155 name = self._platform_impl.get_process_name() |
163 if os.name == 'posix': | 156 if os.name == 'posix': |
164 # On UNIX the name gets truncated to the first 15 characters. | 157 # On UNIX the name gets truncated to the first 15 characters. |
165 # If it matches the first part of the cmdline we return that | 158 # If it matches the first part of the cmdline we return that |
166 # one instead because it's usually more explicative. | 159 # one instead because it's usually more explicative. |
167 # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". | 160 # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". |
(...skipping 10 matching lines...) Expand all Loading... |
178 def exe(self): | 171 def exe(self): |
179 """The process executable as an absolute path name.""" | 172 """The process executable as an absolute path name.""" |
180 exe = self._platform_impl.get_process_exe() | 173 exe = self._platform_impl.get_process_exe() |
181 # if we have the cmdline but not the exe, figure it out from argv[0] | 174 # if we have the cmdline but not the exe, figure it out from argv[0] |
182 if not exe: | 175 if not exe: |
183 cmdline = self.cmdline | 176 cmdline = self.cmdline |
184 if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): | 177 if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): |
185 _exe = os.path.realpath(cmdline[0]) | 178 _exe = os.path.realpath(cmdline[0]) |
186 if os.path.isfile(_exe) and os.access(_exe, os.X_OK): | 179 if os.path.isfile(_exe) and os.access(_exe, os.X_OK): |
187 return _exe | 180 return _exe |
| 181 if not exe: |
| 182 raise AccessDenied(self.pid, self._platform_impl._process_name) |
188 return exe | 183 return exe |
189 | 184 |
190 @property | 185 @property |
191 def path(self): | |
192 msg = "'path' property is deprecated; use 'os.path.dirname(exe)' instead
" | |
193 warnings.warn(msg, DeprecationWarning) | |
194 return os.path.dirname(self.exe) | |
195 | |
196 @property | |
197 def cmdline(self): | 186 def cmdline(self): |
198 """The command line process has been called with.""" | 187 """The command line process has been called with.""" |
199 return self._platform_impl.get_process_cmdline() | 188 return self._platform_impl.get_process_cmdline() |
200 | 189 |
201 @property | 190 @property |
202 def uid(self): | 191 def status(self): |
203 """The real user id of the current process.""" | 192 """The process current status as a STATUS_* constant.""" |
204 return self._platform_impl.get_process_uid() | 193 return self._platform_impl.get_process_status() |
205 | 194 |
206 @property | 195 @property |
207 def gid(self): | 196 def nice(self): |
208 """The real group id of the current process.""" | 197 """Get or set process niceness (priority).""" |
209 return self._platform_impl.get_process_gid() | 198 return self._platform_impl.get_process_nice() |
| 199 |
| 200 @nice.setter |
| 201 def nice(self, value): |
| 202 # invoked on "p.nice = num"; change process niceness |
| 203 return self._platform_impl.set_process_nice(value) |
| 204 |
| 205 if os.name == 'posix': |
| 206 |
| 207 @property |
| 208 def uids(self): |
| 209 """Return a named tuple denoting the process real, |
| 210 effective, and saved user ids. |
| 211 """ |
| 212 return self._platform_impl.get_process_uids() |
| 213 |
| 214 @property |
| 215 def gids(self): |
| 216 """Return a named tuple denoting the process real, |
| 217 effective, and saved group ids. |
| 218 """ |
| 219 return self._platform_impl.get_process_gids() |
| 220 |
| 221 @property |
| 222 def terminal(self): |
| 223 """The terminal associated with this process, if any, |
| 224 else None. |
| 225 """ |
| 226 return self._platform_impl.get_process_terminal() |
210 | 227 |
211 @property | 228 @property |
212 def username(self): | 229 def username(self): |
213 """The name of the user that owns the process.""" | 230 """The name of the user that owns the process. |
| 231 On UNIX this is calculated by using *real* process uid. |
| 232 """ |
214 if os.name == 'posix': | 233 if os.name == 'posix': |
215 if pwd is None: | 234 if pwd is None: |
216 # might happen on compiled-from-sources python | 235 # might happen if python was installed from sources |
217 raise ImportError("requires pwd module shipped with standard pyt
hon") | 236 raise ImportError("requires pwd module shipped with standard pyt
hon") |
218 return pwd.getpwuid(self.uid).pw_name | 237 return pwd.getpwuid(self.uids.real).pw_name |
219 else: | 238 else: |
220 return self._platform_impl.get_process_username() | 239 return self._platform_impl.get_process_username() |
221 | 240 |
222 @property | 241 @property |
223 def create_time(self): | 242 def create_time(self): |
224 """The process creation time as a floating point number | 243 """The process creation time as a floating point number |
225 expressed in seconds since the epoch, in UTC. | 244 expressed in seconds since the epoch, in UTC. |
226 """ | 245 """ |
227 return self._platform_impl.get_process_create_time() | 246 return self._platform_impl.get_process_create_time() |
228 | 247 |
229 # available for Windows and Linux only | 248 # available for Windows and Linux only |
230 if hasattr(PlatformProcess, "get_process_cwd"): | 249 if hasattr(_psplatform.Process, "get_process_cwd"): |
| 250 |
231 def getcwd(self): | 251 def getcwd(self): |
232 """Return a string representing the process current working | 252 """Return a string representing the process current working |
233 directory. | 253 directory. |
234 """ | 254 """ |
235 return self._platform_impl.get_process_cwd() | 255 return self._platform_impl.get_process_cwd() |
236 | 256 |
| 257 # Linux, BSD and Windows only |
| 258 if hasattr(_psplatform.Process, "get_process_io_counters"): |
| 259 |
| 260 def get_io_counters(self): |
| 261 """Return process I/O statistics as a namedtuple including |
| 262 the number of read/write calls performed and the amount of |
| 263 bytes read and written by the process. |
| 264 """ |
| 265 return self._platform_impl.get_process_io_counters() |
| 266 |
| 267 # available only on Linux |
| 268 if hasattr(_psplatform.Process, "get_process_ionice"): |
| 269 |
| 270 def get_ionice(self): |
| 271 """Return process I/O niceness (priority) as a namedtuple.""" |
| 272 return self._platform_impl.get_process_ionice() |
| 273 |
| 274 def set_ionice(self, ioclass, value=None): |
| 275 """Set process I/O niceness (priority). |
| 276 ioclass is one of the IOPRIO_CLASS_* constants. |
| 277 iodata is a number which goes from 0 to 7. The higher the |
| 278 value, the lower the I/O priority of the process. |
| 279 """ |
| 280 return self._platform_impl.set_process_ionice(ioclass, value) |
| 281 |
237 def get_num_threads(self): | 282 def get_num_threads(self): |
238 """Return the number of threads used by this process.""" | 283 """Return the number of threads used by this process.""" |
239 return self._platform_impl.get_process_num_threads() | 284 return self._platform_impl.get_process_num_threads() |
240 | 285 |
| 286 def get_threads(self): |
| 287 """Return threads opened by process as a list of namedtuples |
| 288 including thread id and thread CPU times (user/system). |
| 289 """ |
| 290 return self._platform_impl.get_process_threads() |
| 291 |
241 def get_children(self): | 292 def get_children(self): |
242 """Return the children of this process as a list of Process | 293 """Return the children of this process as a list of Process |
243 objects. | 294 objects. |
244 """ | 295 """ |
245 if not self.is_running(): | 296 if not self.is_running(): |
246 name = self._platform_impl._process_name | 297 name = self._platform_impl._process_name |
247 raise NoSuchProcess(self.pid, name) | 298 raise NoSuchProcess(self.pid, name) |
248 retlist = [] | 299 retlist = [] |
249 for proc in process_iter(): | 300 for proc in process_iter(): |
250 try: | 301 try: |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 return 0.0 | 348 return 0.0 |
298 # the utilization of a single CPU | 349 # the utilization of a single CPU |
299 single_cpu_percent = overall_percent * NUM_CPUS | 350 single_cpu_percent = overall_percent * NUM_CPUS |
300 # ugly hack to avoid troubles with float precision issues | 351 # ugly hack to avoid troubles with float precision issues |
301 if single_cpu_percent > 100.0: | 352 if single_cpu_percent > 100.0: |
302 return 100.0 | 353 return 100.0 |
303 return round(single_cpu_percent, 1) | 354 return round(single_cpu_percent, 1) |
304 | 355 |
305 def get_cpu_times(self): | 356 def get_cpu_times(self): |
306 """Return a tuple whose values are process CPU user and system | 357 """Return a tuple whose values are process CPU user and system |
307 time. These are the same first two values that os.times() | 358 times. The same as os.times() but per-process. |
308 returns for the current process. | |
309 """ | 359 """ |
310 return self._platform_impl.get_cpu_times() | 360 return self._platform_impl.get_cpu_times() |
311 | 361 |
312 def get_memory_info(self): | 362 def get_memory_info(self): |
313 """Return a tuple representing RSS (Resident Set Size) and VMS | 363 """Return a tuple representing RSS (Resident Set Size) and VMS |
314 (Virtual Memory Size) in bytes. | 364 (Virtual Memory Size) in bytes. |
315 | 365 |
316 On UNIX RSS and VMS are the same values shown by ps. | 366 On UNIX RSS and VMS are the same values shown by ps. |
317 | 367 |
318 On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns | 368 On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns |
319 of taskmgr.exe. | 369 of taskmgr.exe. |
320 """ | 370 """ |
321 return self._platform_impl.get_memory_info() | 371 return self._platform_impl.get_memory_info() |
322 | 372 |
323 def get_memory_percent(self): | 373 def get_memory_percent(self): |
324 """Compare physical system memory to process resident memory and | 374 """Compare physical system memory to process resident memory and |
325 calculate process memory utilization as a percentage. | 375 calculate process memory utilization as a percentage. |
326 """ | 376 """ |
327 rss = self._platform_impl.get_memory_info()[0] | 377 rss = self._platform_impl.get_memory_info()[0] |
328 try: | 378 try: |
329 return (rss / float(TOTAL_PHYMEM)) * 100 | 379 return (rss / float(TOTAL_PHYMEM)) * 100 |
330 except ZeroDivisionError: | 380 except ZeroDivisionError: |
331 return 0.0 | 381 return 0.0 |
332 | 382 |
333 def get_open_files(self): | 383 def get_open_files(self): |
334 """Return files opened by process as a list of namedtuples | 384 """Return files opened by process as a list of namedtuples |
335 including absolute file name and file descriptor. | 385 including absolute file name and file descriptor number. |
336 """ | 386 """ |
337 return self._platform_impl.get_open_files() | 387 return self._platform_impl.get_open_files() |
338 | 388 |
339 def get_connections(self): | 389 def get_connections(self): |
340 """Return TCP and UPD connections opened by process as a list | 390 """Return TCP and UPD connections opened by process as a list |
341 of namedtuple/s. | 391 of namedtuples. |
342 For third party processes (!= os.getpid()) results can differ | 392 On BSD and OSX results for third party processes (!= os.getpid()) |
343 depending on user privileges. | 393 can differ depending on user privileges. |
344 """ | 394 """ |
345 return self._platform_impl.get_connections() | 395 return self._platform_impl.get_connections() |
346 | 396 |
347 def is_running(self): | 397 def is_running(self): |
348 """Return whether the current process is running in the current | 398 """Return whether this process is running.""" |
349 process list. | |
350 """ | |
351 try: | 399 try: |
352 newproc = Process(self.pid) | 400 # Test for equality with another Process object based |
353 return self == newproc | 401 # on pid and creation time. |
| 402 # This pair is supposed to indentify a Process instance |
| 403 # univocally over the time (the PID alone is not enough as |
| 404 # it might refer to a process which is gone in meantime |
| 405 # and its PID reused by another process). |
| 406 new_self = Process(self.pid) |
| 407 p1 = (self.pid, self.create_time) |
| 408 p2 = (new_self.pid, new_self.create_time) |
354 except NoSuchProcess: | 409 except NoSuchProcess: |
355 return False | 410 return False |
| 411 else: |
| 412 return p1 == p2 |
356 | 413 |
357 def send_signal(self, sig): | 414 def send_signal(self, sig): |
358 """Send a signal to process (see signal module constants). | 415 """Send a signal to process (see signal module constants). |
359 On Windows only SIGTERM is valid and is treated as an alias | 416 On Windows only SIGTERM is valid and is treated as an alias |
360 for kill(). | 417 for kill(). |
361 """ | 418 """ |
362 # safety measure in case the current process has been killed in | 419 # safety measure in case the current process has been killed in |
363 # meantime and the kernel reused its PID | 420 # meantime and the kernel reused its PID |
364 if not self.is_running(): | 421 if not self.is_running(): |
365 name = self._platform_impl._process_name | 422 name = self._platform_impl._process_name |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 # safety measure in case the current process has been killed in | 476 # safety measure in case the current process has been killed in |
420 # meantime and the kernel reused its PID | 477 # meantime and the kernel reused its PID |
421 if not self.is_running(): | 478 if not self.is_running(): |
422 name = self._platform_impl._process_name | 479 name = self._platform_impl._process_name |
423 raise NoSuchProcess(self.pid, name) | 480 raise NoSuchProcess(self.pid, name) |
424 if os.name == 'posix': | 481 if os.name == 'posix': |
425 self.send_signal(signal.SIGKILL) | 482 self.send_signal(signal.SIGKILL) |
426 else: | 483 else: |
427 self._platform_impl.kill_process() | 484 self._platform_impl.kill_process() |
428 | 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 if timeout is not None and not timeout >= 0: |
| 491 raise ValueError("timeout must be a positive integer") |
| 492 return self._platform_impl.process_wait(timeout) |
| 493 |
| 494 |
| 495 class Popen(Process): |
| 496 """A more convenient interface to stdlib subprocess module. |
| 497 It starts a sub process and deals with it exactly as when using |
| 498 subprocess.Popen class but in addition also provides all the |
| 499 property and methods of psutil.Process class in a unique interface: |
| 500 |
| 501 >>> import psutil |
| 502 >>> from subprocess import PIPE |
| 503 >>> p = psutil.Popen(["/usr/bin/python", "-c", "print 'hi'"], stdout=PIPE) |
| 504 >>> p.name |
| 505 'python' |
| 506 >>> p.uids |
| 507 user(real=1000, effective=1000, saved=1000) |
| 508 >>> p.username |
| 509 'giampaolo' |
| 510 >>> p.communicate() |
| 511 ('hi\n', None) |
| 512 >>> p.terminate() |
| 513 >>> p.wait(timeout=2) |
| 514 0 |
| 515 >>> |
| 516 |
| 517 For method names common to both classes such as kill(), terminate() |
| 518 and wait(), psutil.Process implementation takes precedence. |
| 519 |
| 520 For a complete documentation refers to: |
| 521 http://docs.python.org/library/subprocess.html |
| 522 """ |
| 523 |
| 524 def __init__(self, *args, **kwargs): |
| 525 self.__subproc = subprocess.Popen(*args, **kwargs) |
| 526 Process.__init__(self, self.__subproc.pid) |
| 527 |
| 528 def __dir__(self): |
| 529 return list(set(dir(Popen) + dir(subprocess.Popen))) |
| 530 |
| 531 def __getattribute__(self, name): |
| 532 try: |
| 533 return object.__getattribute__(self, name) |
| 534 except AttributeError: |
| 535 try: |
| 536 return object.__getattribute__(self.__subproc, name) |
| 537 except AttributeError: |
| 538 raise AttributeError("%s instance has no attribute '%s'" |
| 539 %(self.__class__.__name__, name)) |
429 | 540 |
430 def process_iter(): | 541 def process_iter(): |
431 """Return an iterator yielding a Process class instances for all | 542 """Return an iterator yielding a Process class instances for all |
432 running processes on the local machine. | 543 running processes on the local machine. |
433 """ | 544 """ |
434 pids = get_pid_list() | 545 pids = get_pid_list() |
435 # for each PID, create a proxyied Process object | |
436 # it will lazy init it's name and path later if required | |
437 for pid in pids: | 546 for pid in pids: |
438 try: | 547 try: |
439 yield Process(pid) | 548 yield Process(pid) |
440 except (NoSuchProcess, AccessDenied): | 549 except (NoSuchProcess, AccessDenied): |
441 continue | 550 continue |
442 | 551 |
443 def get_process_list(): | 552 def get_process_list(): |
444 """Return a list of Process class instances for all running | 553 """Return a list of Process class instances for all running |
445 processes on the local machine. | 554 processes on the local machine. |
446 """ | 555 """ |
447 return list(process_iter()) | 556 return list(process_iter()) |
448 | 557 |
449 def cpu_times(): | 558 def cpu_times(percpu=False): |
450 """Return system CPU times as a CPUTimes object.""" | 559 """Return system-wide CPU times as a namedtuple object. |
451 values = get_system_cpu_times() | 560 Every CPU time represents the time CPU has spent in the given mode. |
452 return CPUTimes(**values) | 561 The attributes availability varies depending on the platform. |
| 562 Here follows a list of all available attributes: |
| 563 - user |
| 564 - system |
| 565 - idle |
| 566 - nice (UNIX) |
| 567 - iowait (Linux) |
| 568 - irq (Linux, FreeBSD) |
| 569 - softirq (Linux) |
| 570 |
| 571 When percpu is True return a list of nameduples for each CPU. |
| 572 First element of the list refers to first CPU, second element |
| 573 to second CPU and so on. |
| 574 The order of the list is consistent across calls. |
| 575 """ |
| 576 if not percpu: |
| 577 return _psplatform.get_system_cpu_times() |
| 578 else: |
| 579 return _psplatform.get_system_per_cpu_times() |
453 | 580 |
454 | 581 |
455 _last_cpu_times = cpu_times() | 582 _last_cpu_times = cpu_times() |
| 583 _last_per_cpu_times = cpu_times(percpu=True) |
456 | 584 |
457 def cpu_percent(interval=0.1): | 585 def cpu_percent(interval=0.1, percpu=False): |
458 """Return a float representing the current system-wide CPU | 586 """Return a float representing the current system-wide CPU |
459 utilization as a percentage. | 587 utilization as a percentage. |
460 | 588 |
461 When interval is > 0.0 compares system CPU times elapsed before | 589 When interval is > 0.0 compares system CPU times elapsed before |
462 and after the interval (blocking). | 590 and after the interval (blocking). |
463 | 591 |
464 When interval is 0.0 or None compares system CPU times elapsed | 592 When interval is 0.0 or None compares system CPU times elapsed |
465 since last call or module import, returning immediately. | 593 since last call or module import, returning immediately. |
466 In this case is recommended for accuracy that this function be | 594 In this case is recommended for accuracy that this function be |
467 called with at least 0.1 seconds between calls. | 595 called with at least 0.1 seconds between calls. |
| 596 |
| 597 When percpu is True returns a list of floats representing the |
| 598 utilization as a percentage for each CPU. |
| 599 First element of the list refers to first CPU, second element |
| 600 to second CPU and so on. |
| 601 The order of the list is consistent across calls. |
468 """ | 602 """ |
469 global _last_cpu_times | 603 global _last_cpu_times |
| 604 global _last_per_cpu_times |
| 605 blocking = interval is not None and interval > 0.0 |
470 | 606 |
471 blocking = interval is not None and interval > 0.0 | 607 def calculate(t1, t2): |
472 if blocking: | 608 t1_all = sum(t1) |
473 t1 = cpu_times() | 609 t1_busy = t1_all - t1.idle |
474 time.sleep(interval) | 610 |
| 611 t2_all = sum(t2) |
| 612 t2_busy = t2_all - t2.idle |
| 613 |
| 614 # this usually indicates a float precision issue |
| 615 if t2_busy <= t1_busy: |
| 616 return 0.0 |
| 617 |
| 618 busy_delta = t2_busy - t1_busy |
| 619 all_delta = t2_all - t1_all |
| 620 busy_perc = (busy_delta / all_delta) * 100 |
| 621 return round(busy_perc, 1) |
| 622 |
| 623 # system-wide usage |
| 624 if not percpu: |
| 625 if blocking: |
| 626 t1 = cpu_times() |
| 627 time.sleep(interval) |
| 628 else: |
| 629 t1 = _last_cpu_times |
| 630 _last_cpu_times = cpu_times() |
| 631 return calculate(t1, _last_cpu_times) |
| 632 # per-cpu usage |
475 else: | 633 else: |
476 t1 = _last_cpu_times | 634 ret = [] |
| 635 if blocking: |
| 636 tot1 = cpu_times(percpu=True) |
| 637 time.sleep(interval) |
| 638 else: |
| 639 tot1 = _last_per_cpu_times |
| 640 _last_per_cpu_times = cpu_times(percpu=True) |
| 641 for t1, t2 in zip(tot1, _last_per_cpu_times): |
| 642 ret.append(calculate(t1, t2)) |
| 643 return ret |
477 | 644 |
478 t1_all = sum(t1) | 645 def phymem_usage(): |
479 t1_busy = t1_all - t1.idle | 646 """Return the amount of total, used and free physical memory |
| 647 on the system in bytes plus the percentage usage. |
| 648 """ |
| 649 return _psplatform.phymem_usage() |
480 | 650 |
481 t2 = cpu_times() | 651 def virtmem_usage(): |
482 t2_all = sum(t2) | 652 """Return the amount of total, used and free virtual memory |
483 t2_busy = t2_all - t2.idle | 653 on the system in bytes plus the percentage usage. |
484 | 654 |
485 _last_cpu_times = t1 | 655 On Linux they match the values returned by free command line utility. |
486 # this usually indicates a float precision issue | 656 On OS X and FreeBSD they represent the same values as returned by |
487 if t2_busy <= t1_busy: | 657 sysctl vm.vmtotal. On Windows they are determined by reading the |
488 return 0.0 | 658 PageFile values of MEMORYSTATUSEX structure. |
| 659 """ |
| 660 return _psplatform.virtmem_usage() |
489 | 661 |
490 busy_delta = t2_busy - t1_busy | 662 def disk_usage(path): |
491 all_delta = t2_all - t1_all | 663 """Return disk usage statistics about the given path as a namedtuple |
492 busy_perc = (busy_delta / all_delta) * 100 | 664 including total, used and free space expressed in bytes plus the |
493 return round(busy_perc, 1) | 665 percentage usage. |
| 666 """ |
| 667 return _psplatform.get_disk_usage(path) |
494 | 668 |
| 669 def disk_partitions(all=False): |
| 670 """Return mounted partitions as a list of namedtuples including |
| 671 device, mount point and filesystem type. |
| 672 |
| 673 If "all" parameter is False return physical devices only and ignore |
| 674 all others. |
| 675 """ |
| 676 return _psplatform.disk_partitions(all) |
| 677 |
| 678 if hasattr(_psplatform, "network_io_counters"): |
| 679 |
| 680 def network_io_counters(pernic=False): |
| 681 """Return network I/O statistics as a namedtuple including: |
| 682 - number of bytes sent |
| 683 - number of bytes received |
| 684 - number of packets sent |
| 685 - number of packets received |
| 686 |
| 687 If pernic is True return the same information for every |
| 688 network interface installed on the system as a dictionary |
| 689 with network interface names as the keys and the namedtuple |
| 690 described above as the values. |
| 691 """ |
| 692 from psutil._common import ntuple_net_iostat |
| 693 rawdict = _psplatform.network_io_counters() |
| 694 if pernic: |
| 695 for nic, fields in rawdict.iteritems(): |
| 696 rawdict[nic] = ntuple_net_iostat(*fields) |
| 697 return rawdict |
| 698 else: |
| 699 bytes_sent, bytes_recv, packets_sent, packets_recv = 0, 0, 0, 0 |
| 700 for _, fields in rawdict.iteritems(): |
| 701 bytes_sent += fields[0] |
| 702 bytes_recv += fields[1] |
| 703 packets_sent += fields[2] |
| 704 packets_recv += fields[3] |
| 705 return ntuple_net_iostat(bytes_sent, bytes_recv, |
| 706 packets_sent, packets_recv) |
| 707 |
| 708 if hasattr(_psplatform, "disk_io_counters"): |
| 709 |
| 710 def disk_io_counters(perdisk=False): |
| 711 """Return system disk I/O statistics as a namedtuple including: |
| 712 - number of bytes read |
| 713 - number of bytes written |
| 714 - number of reads |
| 715 - number of writes |
| 716 - time spent reading from disk (in nanoseconds) |
| 717 - time spent writing to disk (in nanoseconds) |
| 718 |
| 719 If perdisk is True return the same information for every |
| 720 physical disk installed on the system as a dictionary |
| 721 with partition names as the keys and the namedutuple |
| 722 described above as the values. |
| 723 """ |
| 724 from psutil._common import ntuple_disk_iostat |
| 725 rawdict = _psplatform.disk_io_counters() |
| 726 if perdisk: |
| 727 for disk, fields in rawdict.iteritems(): |
| 728 rawdict[disk] = ntuple_disk_iostat(*fields) |
| 729 return rawdict |
| 730 else: |
| 731 reads, writes, rbytes, wbytes, rtime, wtime = 0, 0, 0, 0, 0, 0 |
| 732 for _, fields in rawdict.iteritems(): |
| 733 reads += fields[0] |
| 734 writes += fields[1] |
| 735 rbytes += fields[2] |
| 736 wbytes += fields[3] |
| 737 rtime += fields[4] |
| 738 wtime += fields[5] |
| 739 return ntuple_disk_iostat(reads, writes, rbytes, wbytes, rtime, wtim
e) |
| 740 |
| 741 |
| 742 def _deprecated(replacement): |
| 743 # a decorator which can be used to mark functions as deprecated |
| 744 def outer(fun): |
| 745 def inner(*args, **kwargs): |
| 746 msg = "psutil.%s is deprecated; use %s instead" \ |
| 747 % (fun.__name__, replacement) |
| 748 warnings.warn(msg, category=DeprecationWarning, stacklevel=2) |
| 749 return fun(*args, **kwargs) |
| 750 return inner |
| 751 return outer |
| 752 |
| 753 # --- deprecated functions |
| 754 |
| 755 @_deprecated("psutil.phymem_usage") |
| 756 def avail_phymem(): |
| 757 return phymem_usage().free |
| 758 |
| 759 @_deprecated("psutil.phymem_usage") |
| 760 def used_phymem(): |
| 761 return phymem_usage().used |
| 762 |
| 763 @_deprecated("psutil.virtmem_usage") |
| 764 def total_virtmem(): |
| 765 return virtmem_usage().total |
| 766 |
| 767 @_deprecated("psutil.virtmem_usage") |
| 768 def used_virtmem(): |
| 769 return virtmem_usage().used |
| 770 |
| 771 @_deprecated("psutil.virtmem_usage") |
| 772 def avail_virtmem(): |
| 773 return virtmem_usage().free |
495 | 774 |
496 def test(): | 775 def test(): |
497 """List info of all currently running processes emulating a | 776 """List info of all currently running processes emulating a |
498 ps -aux output. | 777 ps -aux output. |
499 """ | 778 """ |
500 import datetime | 779 import datetime |
501 today_day = datetime.date.today() | 780 today_day = datetime.date.today() |
502 | 781 |
503 def get_process_info(pid): | 782 def get_process_info(pid): |
504 proc = Process(pid) | 783 proc = Process(pid) |
(...skipping 29 matching lines...) Expand all Loading... |
534 try: | 813 try: |
535 line = get_process_info(pid) | 814 line = get_process_info(pid) |
536 except (AccessDenied, NoSuchProcess): | 815 except (AccessDenied, NoSuchProcess): |
537 pass | 816 pass |
538 else: | 817 else: |
539 print line | 818 print line |
540 | 819 |
541 if __name__ == "__main__": | 820 if __name__ == "__main__": |
542 test() | 821 test() |
543 | 822 |
OLD | NEW |