Index: third_party/psutil/psutil/__init__.py |
diff --git a/third_party/psutil/psutil/__init__.py b/third_party/psutil/psutil/__init__.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..09b7955f2434f32c32392723231e42ec95d188b4 |
--- /dev/null |
+++ b/third_party/psutil/psutil/__init__.py |
@@ -0,0 +1,543 @@ |
+#!/usr/bin/env python |
+# |
+# $Id: __init__.py 806 2010-11-12 23:09:35Z g.rodola $ |
+# |
+ |
+"""psutil is a module providing convenience functions for managing |
+processes in a portable way by using Python. |
+""" |
+ |
+__version__ = "0.2.0" |
+version_info = tuple([int(num) for num in __version__.split('.')]) |
+ |
+__all__ = [ |
+ # exceptions |
+ "Error", "NoSuchProcess", "AccessDenied", |
+ # constants |
+ "NUM_CPUS", "TOTAL_PHYMEM", "version_info", "__version__", |
+ # classes |
+ "Process", |
+ # functions |
+ "test", "pid_exists", "get_pid_list", "process_iter", "get_process_list", |
+ "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem", |
+ "used_virtmem", "cpu_times", "cpu_percent", |
+ ] |
+ |
+import sys |
+import os |
+import time |
+import signal |
+import warnings |
+import errno |
+try: |
+ import pwd |
+except ImportError: |
+ pwd = None |
+ |
+from psutil.error import Error, NoSuchProcess, AccessDenied |
+ |
+# import the appropriate module for our platform only |
+if sys.platform.lower().startswith("linux"): |
+ from psutil._pslinux import * |
+ __all__.extend(["cached_phymem", "phymem_buffers"]) |
+ |
+elif sys.platform.lower().startswith("win32"): |
+ from psutil._psmswindows import * |
+ |
+elif sys.platform.lower().startswith("darwin"): |
+ from psutil._psosx import * |
+ |
+elif sys.platform.lower().startswith("freebsd"): |
+ from psutil._psbsd import * |
+ |
+else: |
+ raise NotImplementedError('platform %s is not supported' % sys.platform) |
+ |
+ |
+class CPUTimes: |
+ """This class contains information about CPU times. |
+ It is not used directly but it's returned as an instance by |
+ psutil.cpu_times() function. |
+ |
+ Every CPU time is accessible in form of an attribute and represents |
+ the time CPU has spent in the given mode. |
+ |
+ The attributes availability varies depending on the platform. |
+ Here follows a list of all available attributes: |
+ |
+ - user |
+ - system |
+ - idle |
+ - nice (UNIX) |
+ - iowait (Linux) |
+ - irq (Linux, FreeBSD) |
+ - softirq (Linux) |
+ """ |
+ |
+ def __init__(self, **kwargs): |
+ self.__attrs = [] |
+ for name in kwargs: |
+ setattr(self, name, kwargs[name]) |
+ self.__attrs.append(name) |
+ |
+ def __str__(self): |
+ string = [] |
+ for attr in self.__attrs: |
+ value = getattr(self, attr) |
+ string.append("%s=%s" %(attr, value)) |
+ return '; '.join(string) |
+ |
+ def __iter__(self): |
+ for attr in self.__attrs: |
+ yield getattr(self, attr) |
+ |
+ |
+class Process(object): |
+ """Represents an OS process.""" |
+ |
+ def __init__(self, pid): |
+ """Create a new Process object, raises NoSuchProcess if the PID |
+ does not exist, and ValueError if the parameter is not an |
+ integer PID.""" |
+ if not isinstance(pid, int): |
+ raise ValueError("An integer is required") |
+ if not pid_exists(pid): |
+ raise NoSuchProcess(pid, None, "no process found with PID %s" % pid) |
+ self._pid = pid |
+ # platform-specific modules define an PlatformProcess |
+ # implementation class |
+ self._platform_impl = PlatformProcess(pid) |
+ self._last_sys_cpu_times = None |
+ self._last_proc_cpu_times = None |
+ |
+ def __str__(self): |
+ try: |
+ pid = self.pid |
+ name = repr(self.name) |
+ cmdline = self.cmdline and repr(' '.join(self.cmdline)) |
+ except NoSuchProcess: |
+ details = "(pid=%s (terminated))" % self.pid |
+ except AccessDenied: |
+ details = "(pid=%s)" % (self.pid) |
+ else: |
+ if cmdline: |
+ details = "(pid=%s, name=%s, cmdline=%s)" % (pid, name, cmdline) |
+ else: |
+ details = "(pid=%s, name=%s)" % (pid, name) |
+ return "%s.%s %s" % (self.__class__.__module__, |
+ self.__class__.__name__, details) |
+ |
+ def __repr__(self): |
+ return "<%s at %s>" % (self.__str__(), id(self)) |
+ |
+ def __eq__(self, other): |
+ """Test for equality with another Process object based on pid |
+ and creation time. |
+ """ |
+ h1 = (self.pid, self.create_time) |
+ h2 = (other.pid, other.create_time) |
+ return h1 == h2 |
+ |
+ @property |
+ def pid(self): |
+ """The process pid.""" |
+ return self._pid |
+ |
+ @property |
+ def ppid(self): |
+ """The process parent pid.""" |
+ return self._platform_impl.get_process_ppid() |
+ |
+ @property |
+ def parent(self): |
+ """Return the parent process as a Process object. If no ppid is |
+ known then return None.""" |
+ if self.ppid is not None: |
+ return Process(self.ppid) |
+ return None |
+ |
+ @property |
+ def name(self): |
+ """The process name.""" |
+ name = self._platform_impl.get_process_name() |
+ if os.name == 'posix': |
+ # On UNIX the name gets truncated to the first 15 characters. |
+ # If it matches the first part of the cmdline we return that |
+ # one instead because it's usually more explicative. |
+ # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". |
+ cmdline = self.cmdline |
+ if cmdline: |
+ extended_name = os.path.basename(cmdline[0]) |
+ if extended_name.startswith(name): |
+ name = extended_name |
+ # XXX - perhaps needs refactoring |
+ self._platform_impl._process_name = name |
+ return name |
+ |
+ @property |
+ def exe(self): |
+ """The process executable as an absolute path name.""" |
+ exe = self._platform_impl.get_process_exe() |
+ # if we have the cmdline but not the exe, figure it out from argv[0] |
+ if not exe: |
+ cmdline = self.cmdline |
+ if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): |
+ _exe = os.path.realpath(cmdline[0]) |
+ if os.path.isfile(_exe) and os.access(_exe, os.X_OK): |
+ return _exe |
+ return exe |
+ |
+ @property |
+ def path(self): |
+ msg = "'path' property is deprecated; use 'os.path.dirname(exe)' instead" |
+ warnings.warn(msg, DeprecationWarning) |
+ return os.path.dirname(self.exe) |
+ |
+ @property |
+ def cmdline(self): |
+ """The command line process has been called with.""" |
+ return self._platform_impl.get_process_cmdline() |
+ |
+ @property |
+ def uid(self): |
+ """The real user id of the current process.""" |
+ return self._platform_impl.get_process_uid() |
+ |
+ @property |
+ def gid(self): |
+ """The real group id of the current process.""" |
+ return self._platform_impl.get_process_gid() |
+ |
+ @property |
+ def username(self): |
+ """The name of the user that owns the process.""" |
+ if os.name == 'posix': |
+ if pwd is None: |
+ # might happen on compiled-from-sources python |
+ raise ImportError("requires pwd module shipped with standard python") |
+ return pwd.getpwuid(self.uid).pw_name |
+ else: |
+ return self._platform_impl.get_process_username() |
+ |
+ @property |
+ def create_time(self): |
+ """The process creation time as a floating point number |
+ expressed in seconds since the epoch, in UTC. |
+ """ |
+ return self._platform_impl.get_process_create_time() |
+ |
+ # available for Windows and Linux only |
+ if hasattr(PlatformProcess, "get_process_cwd"): |
+ def getcwd(self): |
+ """Return a string representing the process current working |
+ directory. |
+ """ |
+ return self._platform_impl.get_process_cwd() |
+ |
+ def get_num_threads(self): |
+ """Return the number of threads used by this process.""" |
+ return self._platform_impl.get_process_num_threads() |
+ |
+ def get_children(self): |
+ """Return the children of this process as a list of Process |
+ objects. |
+ """ |
+ if not self.is_running(): |
+ name = self._platform_impl._process_name |
+ raise NoSuchProcess(self.pid, name) |
+ retlist = [] |
+ for proc in process_iter(): |
+ try: |
+ if proc.ppid == self.pid: |
+ retlist.append(proc) |
+ except NoSuchProcess: |
+ pass |
+ return retlist |
+ |
+ def get_cpu_percent(self, interval=0.1): |
+ """Return a float representing the current process CPU |
+ utilization as a percentage. |
+ |
+ When interval is > 0.0 compares process times to system CPU |
+ times elapsed before and after the interval (blocking). |
+ |
+ When interval is 0.0 or None compares process times to system CPU |
+ times elapsed since last call, returning immediately. |
+ In this case is recommended for accuracy that this function be |
+ called with at least 0.1 seconds between calls. |
+ """ |
+ blocking = interval is not None and interval > 0.0 |
+ if blocking: |
+ st1 = sum(cpu_times()) |
+ pt1 = self._platform_impl.get_cpu_times() |
+ time.sleep(interval) |
+ st2 = sum(cpu_times()) |
+ pt2 = self._platform_impl.get_cpu_times() |
+ else: |
+ st1 = self._last_sys_cpu_times |
+ pt1 = self._last_proc_cpu_times |
+ st2 = sum(cpu_times()) |
+ pt2 = self._platform_impl.get_cpu_times() |
+ if st1 is None or pt1 is None: |
+ self._last_sys_cpu_times = st2 |
+ self._last_proc_cpu_times = pt2 |
+ return 0.0 |
+ |
+ delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) |
+ delta_time = st2 - st1 |
+ # reset values for next call in case of interval == None |
+ self._last_sys_cpu_times = st2 |
+ self._last_proc_cpu_times = pt2 |
+ |
+ try: |
+ # the utilization split between all CPUs |
+ overall_percent = (delta_proc / delta_time) * 100 |
+ except ZeroDivisionError: |
+ # interval was too low |
+ return 0.0 |
+ # the utilization of a single CPU |
+ single_cpu_percent = overall_percent * NUM_CPUS |
+ # ugly hack to avoid troubles with float precision issues |
+ if single_cpu_percent > 100.0: |
+ return 100.0 |
+ return round(single_cpu_percent, 1) |
+ |
+ def get_cpu_times(self): |
+ """Return a tuple whose values are process CPU user and system |
+ time. These are the same first two values that os.times() |
+ returns for the current process. |
+ """ |
+ return self._platform_impl.get_cpu_times() |
+ |
+ def get_memory_info(self): |
+ """Return a tuple representing RSS (Resident Set Size) and VMS |
+ (Virtual Memory Size) in bytes. |
+ |
+ On UNIX RSS and VMS are the same values shown by ps. |
+ |
+ On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns |
+ of taskmgr.exe. |
+ """ |
+ return self._platform_impl.get_memory_info() |
+ |
+ def get_memory_percent(self): |
+ """Compare physical system memory to process resident memory and |
+ calculate process memory utilization as a percentage. |
+ """ |
+ rss = self._platform_impl.get_memory_info()[0] |
+ try: |
+ return (rss / float(TOTAL_PHYMEM)) * 100 |
+ except ZeroDivisionError: |
+ return 0.0 |
+ |
+ def get_open_files(self): |
+ """Return files opened by process as a list of namedtuples |
+ including absolute file name and file descriptor. |
+ """ |
+ return self._platform_impl.get_open_files() |
+ |
+ def get_connections(self): |
+ """Return TCP and UPD connections opened by process as a list |
+ of namedtuple/s. |
+ For third party processes (!= os.getpid()) results can differ |
+ depending on user privileges. |
+ """ |
+ return self._platform_impl.get_connections() |
+ |
+ def is_running(self): |
+ """Return whether the current process is running in the current |
+ process list. |
+ """ |
+ try: |
+ newproc = Process(self.pid) |
+ return self == newproc |
+ except NoSuchProcess: |
+ return False |
+ |
+ def send_signal(self, sig): |
+ """Send a signal to process (see signal module constants). |
+ On Windows only SIGTERM is valid and is treated as an alias |
+ for kill(). |
+ """ |
+ # safety measure in case the current process has been killed in |
+ # meantime and the kernel reused its PID |
+ if not self.is_running(): |
+ name = self._platform_impl._process_name |
+ raise NoSuchProcess(self.pid, name) |
+ if os.name == 'posix': |
+ try: |
+ os.kill(self.pid, sig) |
+ except OSError, err: |
+ name = self._platform_impl._process_name |
+ if err.errno == errno.ESRCH: |
+ raise NoSuchProcess(self.pid, name) |
+ if err.errno == errno.EPERM: |
+ raise AccessDenied(self.pid, name) |
+ raise |
+ else: |
+ if sig == signal.SIGTERM: |
+ self._platform_impl.kill_process() |
+ else: |
+ raise ValueError("only SIGTERM is supported on Windows") |
+ |
+ def suspend(self): |
+ """Suspend process execution.""" |
+ # safety measure in case the current process has been killed in |
+ # meantime and the kernel reused its PID |
+ if not self.is_running(): |
+ name = self._platform_impl._process_name |
+ raise NoSuchProcess(self.pid, name) |
+ # windows |
+ if hasattr(self._platform_impl, "suspend_process"): |
+ self._platform_impl.suspend_process() |
+ else: |
+ # posix |
+ self.send_signal(signal.SIGSTOP) |
+ |
+ def resume(self): |
+ """Resume process execution.""" |
+ # safety measure in case the current process has been killed in |
+ # meantime and the kernel reused its PID |
+ if not self.is_running(): |
+ name = self._platform_impl._process_name |
+ raise NoSuchProcess(self.pid, name) |
+ # windows |
+ if hasattr(self._platform_impl, "resume_process"): |
+ self._platform_impl.resume_process() |
+ else: |
+ # posix |
+ self.send_signal(signal.SIGCONT) |
+ |
+ def terminate(self): |
+ """Terminate the process with SIGTERM. |
+ On Windows this is an alias for kill(). |
+ """ |
+ self.send_signal(signal.SIGTERM) |
+ |
+ def kill(self): |
+ """Kill the current process.""" |
+ # safety measure in case the current process has been killed in |
+ # meantime and the kernel reused its PID |
+ if not self.is_running(): |
+ name = self._platform_impl._process_name |
+ raise NoSuchProcess(self.pid, name) |
+ if os.name == 'posix': |
+ self.send_signal(signal.SIGKILL) |
+ else: |
+ self._platform_impl.kill_process() |
+ |
+ |
+def process_iter(): |
+ """Return an iterator yielding a Process class instances for all |
+ running processes on the local machine. |
+ """ |
+ pids = get_pid_list() |
+ # for each PID, create a proxyied Process object |
+ # it will lazy init it's name and path later if required |
+ for pid in pids: |
+ try: |
+ yield Process(pid) |
+ except (NoSuchProcess, AccessDenied): |
+ continue |
+ |
+def get_process_list(): |
+ """Return a list of Process class instances for all running |
+ processes on the local machine. |
+ """ |
+ return list(process_iter()) |
+ |
+def cpu_times(): |
+ """Return system CPU times as a CPUTimes object.""" |
+ values = get_system_cpu_times() |
+ return CPUTimes(**values) |
+ |
+ |
+_last_cpu_times = cpu_times() |
+ |
+def cpu_percent(interval=0.1): |
+ """Return a float representing the current system-wide CPU |
+ utilization as a percentage. |
+ |
+ When interval is > 0.0 compares system CPU times elapsed before |
+ and after the interval (blocking). |
+ |
+ When interval is 0.0 or None compares system CPU times elapsed |
+ since last call or module import, returning immediately. |
+ In this case is recommended for accuracy that this function be |
+ called with at least 0.1 seconds between calls. |
+ """ |
+ global _last_cpu_times |
+ |
+ blocking = interval is not None and interval > 0.0 |
+ if blocking: |
+ t1 = cpu_times() |
+ time.sleep(interval) |
+ else: |
+ t1 = _last_cpu_times |
+ |
+ t1_all = sum(t1) |
+ t1_busy = t1_all - t1.idle |
+ |
+ t2 = cpu_times() |
+ t2_all = sum(t2) |
+ t2_busy = t2_all - t2.idle |
+ |
+ _last_cpu_times = t1 |
+ # this usually indicates a float precision issue |
+ if t2_busy <= t1_busy: |
+ return 0.0 |
+ |
+ busy_delta = t2_busy - t1_busy |
+ all_delta = t2_all - t1_all |
+ busy_perc = (busy_delta / all_delta) * 100 |
+ return round(busy_perc, 1) |
+ |
+ |
+def test(): |
+ """List info of all currently running processes emulating a |
+ ps -aux output. |
+ """ |
+ import datetime |
+ today_day = datetime.date.today() |
+ |
+ def get_process_info(pid): |
+ proc = Process(pid) |
+ user = proc.username |
+ if os.name == 'nt' and '\\' in user: |
+ user = user.split('\\')[1] |
+ pid = proc.pid |
+ cpu = round(proc.get_cpu_percent(interval=None), 1) |
+ mem = round(proc.get_memory_percent(), 1) |
+ rss, vsz = [x / 1024 for x in proc.get_memory_info()] |
+ |
+ # If process has been created today print H:M, else MonthDay |
+ start = datetime.datetime.fromtimestamp(proc.create_time) |
+ if start.date() == today_day: |
+ start = start.strftime("%H:%M") |
+ else: |
+ start = start.strftime("%b%d") |
+ |
+ cputime = time.strftime("%M:%S", time.localtime(sum(proc.get_cpu_times()))) |
+ cmd = ' '.join(proc.cmdline) |
+ # where cmdline is not available UNIX shows process name between |
+ # [] parentheses |
+ if not cmd: |
+ cmd = "[%s]" % proc.name |
+ return "%-9s %-5s %-4s %4s %7s %7s %5s %8s %s" \ |
+ % (user, pid, cpu, mem, vsz, rss, start, cputime, cmd) |
+ |
+ print "%-9s %-5s %-4s %4s %7s %7s %5s %7s %s" \ |
+ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "START", "TIME", "COMMAND") |
+ pids = get_pid_list() |
+ pids.sort() |
+ for pid in pids: |
+ try: |
+ line = get_process_info(pid) |
+ except (AccessDenied, NoSuchProcess): |
+ pass |
+ else: |
+ print line |
+ |
+if __name__ == "__main__": |
+ test() |
+ |