OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # | |
3 # $Id: __init__.py 1142 2011-10-05 18:45:49Z g.rodola $ | |
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. | |
8 | |
9 """psutil is a module providing convenience functions for managing | |
10 processes and gather system information in a portable way by using | |
11 Python. | |
12 """ | |
13 | |
14 __version__ = "0.3.1" | |
15 version_info = tuple([int(num) for num in __version__.split('.')]) | |
16 | |
17 __all__ = [ | |
18 # exceptions | |
19 "Error", "NoSuchProcess", "AccessDenied", "TimeoutExpired", | |
20 # constants | |
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", | |
26 # classes | |
27 "Process", "Popen", | |
28 # functions | |
29 "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list", | |
30 "phymem_usage", "virtmem_usage" | |
31 "cpu_times", "per_cpu_times", "cpu_percent", "per_cpu_percent", | |
32 "network_io_counters", "disk_io_counters", | |
33 ] | |
34 | |
35 import sys | |
36 import os | |
37 import time | |
38 import signal | |
39 import warnings | |
40 import errno | |
41 import subprocess | |
42 try: | |
43 import pwd | |
44 except ImportError: | |
45 pwd = None | |
46 | |
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 ) | |
54 | |
55 # import the appropriate module for our platform only | |
56 if sys.platform.lower().startswith("linux"): | |
57 import psutil._pslinux as _psplatform | |
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 | |
66 | |
67 elif sys.platform.lower().startswith("win32"): | |
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) | |
75 | |
76 elif sys.platform.lower().startswith("darwin"): | |
77 import psutil._psosx as _psplatform | |
78 | |
79 elif sys.platform.lower().startswith("freebsd"): | |
80 import psutil._psbsd as _psplatform | |
81 | |
82 else: | |
83 raise NotImplementedError('platform %s is not supported' % sys.platform) | |
84 | |
85 __all__.extend(_psplatform.__extra__all__) | |
86 | |
87 NUM_CPUS = _psplatform.NUM_CPUS | |
88 BOOT_TIME = _psplatform.BOOT_TIME | |
89 TOTAL_PHYMEM = _psplatform.phymem_usage()[0] | |
90 | |
91 get_pid_list = _psplatform.get_pid_list | |
92 pid_exists = _psplatform.pid_exists | |
93 | |
94 | |
95 class Process(object): | |
96 """Represents an OS process.""" | |
97 | |
98 def __init__(self, pid): | |
99 """Create a new Process object, raises NoSuchProcess if the PID | |
100 does not exist, and ValueError if the parameter is not an | |
101 integer PID. | |
102 """ | |
103 if not isinstance(pid, int): | |
104 raise ValueError("an integer is required") | |
105 if not pid_exists(pid): | |
106 raise NoSuchProcess(pid, None, "no process found with pid %s" % pid) | |
107 self._pid = pid | |
108 # platform-specific modules define an _psplatform.Process | |
109 # implementation class | |
110 self._platform_impl = _psplatform.Process(pid) | |
111 self._last_sys_cpu_times = None | |
112 self._last_proc_cpu_times = None | |
113 | |
114 def __str__(self): | |
115 try: | |
116 pid = self.pid | |
117 name = repr(self.name) | |
118 except NoSuchProcess: | |
119 details = "(pid=%s (terminated))" % self.pid | |
120 except AccessDenied: | |
121 details = "(pid=%s)" % (self.pid) | |
122 else: | |
123 details = "(pid=%s, name=%s)" % (pid, name) | |
124 return "%s.%s%s" % (self.__class__.__module__, | |
125 self.__class__.__name__, details) | |
126 | |
127 def __repr__(self): | |
128 return "<%s at %s>" % (self.__str__(), id(self)) | |
129 | |
130 @property | |
131 def pid(self): | |
132 """The process pid.""" | |
133 return self._pid | |
134 | |
135 @property | |
136 def ppid(self): | |
137 """The process parent pid.""" | |
138 return self._platform_impl.get_process_ppid() | |
139 | |
140 @property | |
141 def parent(self): | |
142 """Return the parent process as a Process object. If no parent | |
143 pid is known return None. | |
144 """ | |
145 ppid = self.ppid | |
146 if ppid is not None: | |
147 try: | |
148 return Process(ppid) | |
149 except NoSuchProcess: | |
150 pass | |
151 | |
152 @property | |
153 def name(self): | |
154 """The process name.""" | |
155 name = self._platform_impl.get_process_name() | |
156 if os.name == 'posix': | |
157 # On UNIX the name gets truncated to the first 15 characters. | |
158 # If it matches the first part of the cmdline we return that | |
159 # one instead because it's usually more explicative. | |
160 # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". | |
161 cmdline = self.cmdline | |
162 if cmdline: | |
163 extended_name = os.path.basename(cmdline[0]) | |
164 if extended_name.startswith(name): | |
165 name = extended_name | |
166 # XXX - perhaps needs refactoring | |
167 self._platform_impl._process_name = name | |
168 return name | |
169 | |
170 @property | |
171 def exe(self): | |
172 """The process executable as an absolute path name.""" | |
173 exe = self._platform_impl.get_process_exe() | |
174 # if we have the cmdline but not the exe, figure it out from argv[0] | |
175 if not exe: | |
176 cmdline = self.cmdline | |
177 if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): | |
178 _exe = os.path.realpath(cmdline[0]) | |
179 if os.path.isfile(_exe) and os.access(_exe, os.X_OK): | |
180 return _exe | |
181 if not exe: | |
182 raise AccessDenied(self.pid, self._platform_impl._process_name) | |
183 return exe | |
184 | |
185 @property | |
186 def cmdline(self): | |
187 """The command line process has been called with.""" | |
188 return self._platform_impl.get_process_cmdline() | |
189 | |
190 @property | |
191 def status(self): | |
192 """The process current status as a STATUS_* constant.""" | |
193 return self._platform_impl.get_process_status() | |
194 | |
195 @property | |
196 def nice(self): | |
197 """Get or set process niceness (priority).""" | |
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() | |
227 | |
228 @property | |
229 def username(self): | |
230 """The name of the user that owns the process. | |
231 On UNIX this is calculated by using *real* process uid. | |
232 """ | |
233 if os.name == 'posix': | |
234 if pwd is None: | |
235 # might happen if python was installed from sources | |
236 raise ImportError("requires pwd module shipped with standard pyt
hon") | |
237 return pwd.getpwuid(self.uids.real).pw_name | |
238 else: | |
239 return self._platform_impl.get_process_username() | |
240 | |
241 @property | |
242 def create_time(self): | |
243 """The process creation time as a floating point number | |
244 expressed in seconds since the epoch, in UTC. | |
245 """ | |
246 return self._platform_impl.get_process_create_time() | |
247 | |
248 # available for Windows and Linux only | |
249 if hasattr(_psplatform.Process, "get_process_cwd"): | |
250 | |
251 def getcwd(self): | |
252 """Return a string representing the process current working | |
253 directory. | |
254 """ | |
255 return self._platform_impl.get_process_cwd() | |
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 | |
282 def get_num_threads(self): | |
283 """Return the number of threads used by this process.""" | |
284 return self._platform_impl.get_process_num_threads() | |
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 | |
292 def get_children(self): | |
293 """Return the children of this process as a list of Process | |
294 objects. | |
295 """ | |
296 if not self.is_running(): | |
297 name = self._platform_impl._process_name | |
298 raise NoSuchProcess(self.pid, name) | |
299 retlist = [] | |
300 for proc in process_iter(): | |
301 try: | |
302 if proc.ppid == self.pid: | |
303 retlist.append(proc) | |
304 except NoSuchProcess: | |
305 pass | |
306 return retlist | |
307 | |
308 def get_cpu_percent(self, interval=0.1): | |
309 """Return a float representing the current process CPU | |
310 utilization as a percentage. | |
311 | |
312 When interval is > 0.0 compares process times to system CPU | |
313 times elapsed before and after the interval (blocking). | |
314 | |
315 When interval is 0.0 or None compares process times to system CPU | |
316 times elapsed since last call, returning immediately. | |
317 In this case is recommended for accuracy that this function be | |
318 called with at least 0.1 seconds between calls. | |
319 """ | |
320 blocking = interval is not None and interval > 0.0 | |
321 if blocking: | |
322 st1 = sum(cpu_times()) | |
323 pt1 = self._platform_impl.get_cpu_times() | |
324 time.sleep(interval) | |
325 st2 = sum(cpu_times()) | |
326 pt2 = self._platform_impl.get_cpu_times() | |
327 else: | |
328 st1 = self._last_sys_cpu_times | |
329 pt1 = self._last_proc_cpu_times | |
330 st2 = sum(cpu_times()) | |
331 pt2 = self._platform_impl.get_cpu_times() | |
332 if st1 is None or pt1 is None: | |
333 self._last_sys_cpu_times = st2 | |
334 self._last_proc_cpu_times = pt2 | |
335 return 0.0 | |
336 | |
337 delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) | |
338 delta_time = st2 - st1 | |
339 # reset values for next call in case of interval == None | |
340 self._last_sys_cpu_times = st2 | |
341 self._last_proc_cpu_times = pt2 | |
342 | |
343 try: | |
344 # the utilization split between all CPUs | |
345 overall_percent = (delta_proc / delta_time) * 100 | |
346 except ZeroDivisionError: | |
347 # interval was too low | |
348 return 0.0 | |
349 # the utilization of a single CPU | |
350 single_cpu_percent = overall_percent * NUM_CPUS | |
351 # ugly hack to avoid troubles with float precision issues | |
352 if single_cpu_percent > 100.0: | |
353 return 100.0 | |
354 return round(single_cpu_percent, 1) | |
355 | |
356 def get_cpu_times(self): | |
357 """Return a tuple whose values are process CPU user and system | |
358 times. The same as os.times() but per-process. | |
359 """ | |
360 return self._platform_impl.get_cpu_times() | |
361 | |
362 def get_memory_info(self): | |
363 """Return a tuple representing RSS (Resident Set Size) and VMS | |
364 (Virtual Memory Size) in bytes. | |
365 | |
366 On UNIX RSS and VMS are the same values shown by ps. | |
367 | |
368 On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns | |
369 of taskmgr.exe. | |
370 """ | |
371 return self._platform_impl.get_memory_info() | |
372 | |
373 def get_memory_percent(self): | |
374 """Compare physical system memory to process resident memory and | |
375 calculate process memory utilization as a percentage. | |
376 """ | |
377 rss = self._platform_impl.get_memory_info()[0] | |
378 try: | |
379 return (rss / float(TOTAL_PHYMEM)) * 100 | |
380 except ZeroDivisionError: | |
381 return 0.0 | |
382 | |
383 def get_open_files(self): | |
384 """Return files opened by process as a list of namedtuples | |
385 including absolute file name and file descriptor number. | |
386 """ | |
387 return self._platform_impl.get_open_files() | |
388 | |
389 def get_connections(self): | |
390 """Return TCP and UPD connections opened by process as a list | |
391 of namedtuples. | |
392 On BSD and OSX results for third party processes (!= os.getpid()) | |
393 can differ depending on user privileges. | |
394 """ | |
395 return self._platform_impl.get_connections() | |
396 | |
397 def is_running(self): | |
398 """Return whether this process is running.""" | |
399 try: | |
400 # Test for equality with another Process object based | |
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) | |
409 except NoSuchProcess: | |
410 return False | |
411 else: | |
412 return p1 == p2 | |
413 | |
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 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)) | |
540 | |
541 def process_iter(): | |
542 """Return an iterator yielding a Process class instances for all | |
543 running processes on the local machine. | |
544 """ | |
545 pids = get_pid_list() | |
546 for pid in pids: | |
547 try: | |
548 yield Process(pid) | |
549 except (NoSuchProcess, AccessDenied): | |
550 continue | |
551 | |
552 def get_process_list(): | |
553 """Return a list of Process class instances for all running | |
554 processes on the local machine. | |
555 """ | |
556 return list(process_iter()) | |
557 | |
558 def cpu_times(percpu=False): | |
559 """Return system-wide CPU times as a namedtuple object. | |
560 Every CPU time represents the time CPU has spent in the given mode. | |
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() | |
580 | |
581 | |
582 _last_cpu_times = cpu_times() | |
583 _last_per_cpu_times = cpu_times(percpu=True) | |
584 | |
585 def cpu_percent(interval=0.1, percpu=False): | |
586 """Return a float representing the current system-wide CPU | |
587 utilization as a percentage. | |
588 | |
589 When interval is > 0.0 compares system CPU times elapsed before | |
590 and after the interval (blocking). | |
591 | |
592 When interval is 0.0 or None compares system CPU times elapsed | |
593 since last call or module import, returning immediately. | |
594 In this case is recommended for accuracy that this function be | |
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. | |
602 """ | |
603 global _last_cpu_times | |
604 global _last_per_cpu_times | |
605 blocking = interval is not None and interval > 0.0 | |
606 | |
607 def calculate(t1, t2): | |
608 t1_all = sum(t1) | |
609 t1_busy = t1_all - t1.idle | |
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 | |
633 else: | |
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 | |
644 | |
645 def phymem_usage(): | |
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() | |
650 | |
651 def virtmem_usage(): | |
652 """Return the amount of total, used and free virtual memory | |
653 on the system in bytes plus the percentage usage. | |
654 | |
655 On Linux they match the values returned by free command line utility. | |
656 On OS X and FreeBSD they represent the same values as returned by | |
657 sysctl vm.vmtotal. On Windows they are determined by reading the | |
658 PageFile values of MEMORYSTATUSEX structure. | |
659 """ | |
660 return _psplatform.virtmem_usage() | |
661 | |
662 def disk_usage(path): | |
663 """Return disk usage statistics about the given path as a namedtuple | |
664 including total, used and free space expressed in bytes plus the | |
665 percentage usage. | |
666 """ | |
667 return _psplatform.get_disk_usage(path) | |
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 | |
774 | |
775 def test(): | |
776 """List info of all currently running processes emulating a | |
777 ps -aux output. | |
778 """ | |
779 import datetime | |
780 today_day = datetime.date.today() | |
781 | |
782 def get_process_info(pid): | |
783 proc = Process(pid) | |
784 user = proc.username | |
785 if os.name == 'nt' and '\\' in user: | |
786 user = user.split('\\')[1] | |
787 pid = proc.pid | |
788 cpu = round(proc.get_cpu_percent(interval=None), 1) | |
789 mem = round(proc.get_memory_percent(), 1) | |
790 rss, vsz = [x / 1024 for x in proc.get_memory_info()] | |
791 | |
792 # If process has been created today print H:M, else MonthDay | |
793 start = datetime.datetime.fromtimestamp(proc.create_time) | |
794 if start.date() == today_day: | |
795 start = start.strftime("%H:%M") | |
796 else: | |
797 start = start.strftime("%b%d") | |
798 | |
799 cputime = time.strftime("%M:%S", time.localtime(sum(proc.get_cpu_times()
))) | |
800 cmd = ' '.join(proc.cmdline) | |
801 # where cmdline is not available UNIX shows process name between | |
802 # [] parentheses | |
803 if not cmd: | |
804 cmd = "[%s]" % proc.name | |
805 return "%-9s %-5s %-4s %4s %7s %7s %5s %8s %s" \ | |
806 % (user, pid, cpu, mem, vsz, rss, start, cputime, cmd) | |
807 | |
808 print "%-9s %-5s %-4s %4s %7s %7s %5s %7s %s" \ | |
809 % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "START", "TIME", "COMMAND"
) | |
810 pids = get_pid_list() | |
811 pids.sort() | |
812 for pid in pids: | |
813 try: | |
814 line = get_process_info(pid) | |
815 except (AccessDenied, NoSuchProcess): | |
816 pass | |
817 else: | |
818 print line | |
819 | |
820 if __name__ == "__main__": | |
821 test() | |
822 | |
OLD | NEW |