python/psutil/examples/top.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/python/psutil/examples/top.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,202 @@
     1.4 +#!/usr/bin/env python
     1.5 +
     1.6 +# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
     1.7 +# Use of this source code is governed by a BSD-style license that can be
     1.8 +# found in the LICENSE file.
     1.9 +
    1.10 +"""
    1.11 +A clone of top / htop.
    1.12 +
    1.13 +Author: Giampaolo Rodola' <g.rodola@gmail.com>
    1.14 +"""
    1.15 +
    1.16 +import os
    1.17 +import sys
    1.18 +if os.name != 'posix':
    1.19 +    sys.exit('platform not supported')
    1.20 +import time
    1.21 +import curses
    1.22 +import atexit
    1.23 +from datetime import datetime, timedelta
    1.24 +
    1.25 +import psutil
    1.26 +
    1.27 +
    1.28 +# --- curses stuff
    1.29 +def tear_down():
    1.30 +    win.keypad(0)
    1.31 +    curses.nocbreak()
    1.32 +    curses.echo()
    1.33 +    curses.endwin()
    1.34 +
    1.35 +win = curses.initscr()
    1.36 +atexit.register(tear_down)
    1.37 +curses.endwin()
    1.38 +lineno = 0
    1.39 +
    1.40 +def print_line(line, highlight=False):
    1.41 +    """A thin wrapper around curses's addstr()."""
    1.42 +    global lineno
    1.43 +    try:
    1.44 +        if highlight:
    1.45 +            line += " " * (win.getmaxyx()[1] - len(line))
    1.46 +            win.addstr(lineno, 0, line, curses.A_REVERSE)
    1.47 +        else:
    1.48 +            win.addstr(lineno, 0, line, 0)
    1.49 +    except curses.error:
    1.50 +        lineno = 0
    1.51 +        win.refresh()
    1.52 +        raise
    1.53 +    else:
    1.54 +        lineno += 1
    1.55 +# --- /curses stuff
    1.56 +
    1.57 +
    1.58 +def bytes2human(n):
    1.59 +    """
    1.60 +    >>> bytes2human(10000)
    1.61 +    '9K'
    1.62 +    >>> bytes2human(100001221)
    1.63 +    '95M'
    1.64 +    """
    1.65 +    symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
    1.66 +    prefix = {}
    1.67 +    for i, s in enumerate(symbols):
    1.68 +        prefix[s] = 1 << (i+1)*10
    1.69 +    for s in reversed(symbols):
    1.70 +        if n >= prefix[s]:
    1.71 +            value = int(float(n) / prefix[s])
    1.72 +            return '%s%s' % (value, s)
    1.73 +    return "%sB" % n
    1.74 +
    1.75 +def poll(interval):
    1.76 +    # sleep some time
    1.77 +    time.sleep(interval)
    1.78 +    procs = []
    1.79 +    procs_status = {}
    1.80 +    for p in psutil.process_iter():
    1.81 +        try:
    1.82 +            p.dict = p.as_dict(['username', 'get_nice', 'get_memory_info',
    1.83 +                                'get_memory_percent', 'get_cpu_percent',
    1.84 +                                'get_cpu_times', 'name', 'status'])
    1.85 +            try:
    1.86 +                procs_status[str(p.dict['status'])] += 1
    1.87 +            except KeyError:
    1.88 +                procs_status[str(p.dict['status'])] = 1
    1.89 +        except psutil.NoSuchProcess:
    1.90 +            pass
    1.91 +        else:
    1.92 +            procs.append(p)
    1.93 +
    1.94 +    # return processes sorted by CPU percent usage
    1.95 +    processes = sorted(procs, key=lambda p: p.dict['cpu_percent'], reverse=True)
    1.96 +    return (processes, procs_status)
    1.97 +
    1.98 +def print_header(procs_status, num_procs):
    1.99 +    """Print system-related info, above the process list."""
   1.100 +
   1.101 +    def get_dashes(perc):
   1.102 +        dashes =  "|" * int((float(perc) / 10 * 4))
   1.103 +        empty_dashes = " " * (40 - len(dashes))
   1.104 +        return dashes, empty_dashes
   1.105 +
   1.106 +    # cpu usage
   1.107 +    for cpu_num, perc in enumerate(psutil.cpu_percent(interval=0, percpu=True)):
   1.108 +        dashes, empty_dashes = get_dashes(perc)
   1.109 +        print_line(" CPU%-2s [%s%s] %5s%%" % (cpu_num, dashes, empty_dashes,
   1.110 +                                              perc))
   1.111 +    mem = psutil.virtual_memory()
   1.112 +    dashes, empty_dashes = get_dashes(mem.percent)
   1.113 +    used = mem.total - mem.available
   1.114 +    line = " Mem   [%s%s] %5s%% %6s/%s" % (
   1.115 +        dashes, empty_dashes,
   1.116 +        mem.percent,
   1.117 +        str(int(used / 1024 / 1024)) + "M",
   1.118 +        str(int(mem.total / 1024 / 1024)) + "M"
   1.119 +    )
   1.120 +    print_line(line)
   1.121 +
   1.122 +    # swap usage
   1.123 +    swap = psutil.swap_memory()
   1.124 +    dashes, empty_dashes = get_dashes(swap.percent)
   1.125 +    line = " Swap  [%s%s] %5s%% %6s/%s" % (
   1.126 +        dashes, empty_dashes,
   1.127 +        swap.percent,
   1.128 +        str(int(swap.used / 1024 / 1024)) + "M",
   1.129 +        str(int(swap.total / 1024 / 1024)) + "M"
   1.130 +    )
   1.131 +    print_line(line)
   1.132 +
   1.133 +    # processes number and status
   1.134 +    st = []
   1.135 +    for x, y in procs_status.items():
   1.136 +        if y:
   1.137 +            st.append("%s=%s" % (x, y))
   1.138 +    st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1)
   1.139 +    print_line(" Processes: %s (%s)" % (num_procs, ' '.join(st)))
   1.140 +    # load average, uptime
   1.141 +    uptime = datetime.now() - datetime.fromtimestamp(psutil.BOOT_TIME)
   1.142 +    av1, av2, av3 = os.getloadavg()
   1.143 +    line = " Load average: %.2f %.2f %.2f  Uptime: %s" \
   1.144 +            % (av1, av2, av3, str(uptime).split('.')[0])
   1.145 +    print_line(line)
   1.146 +
   1.147 +def refresh_window(procs, procs_status):
   1.148 +    """Print results on screen by using curses."""
   1.149 +    curses.endwin()
   1.150 +    templ = "%-6s %-8s %4s %5s %5s %6s %4s %9s  %2s"
   1.151 +    win.erase()
   1.152 +    header = templ % ("PID", "USER", "NI", "VIRT", "RES", "CPU%", "MEM%",
   1.153 +                      "TIME+", "NAME")
   1.154 +    print_header(procs_status, len(procs))
   1.155 +    print_line("")
   1.156 +    print_line(header, highlight=True)
   1.157 +    for p in procs:
   1.158 +        # TIME+ column shows process CPU cumulative time and it
   1.159 +        # is expressed as: "mm:ss.ms"
   1.160 +        if p.dict['cpu_times'] != None:
   1.161 +            ctime = timedelta(seconds=sum(p.dict['cpu_times']))
   1.162 +            ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60,
   1.163 +                                  str((ctime.seconds % 60)).zfill(2),
   1.164 +                                  str(ctime.microseconds)[:2])
   1.165 +        else:
   1.166 +            ctime = ''
   1.167 +        if p.dict['memory_percent'] is not None:
   1.168 +            p.dict['memory_percent'] = round(p.dict['memory_percent'], 1)
   1.169 +        else:
   1.170 +            p.dict['memory_percent'] = ''
   1.171 +        if p.dict['cpu_percent'] is None:
   1.172 +            p.dict['cpu_percent'] = ''
   1.173 +        if p.dict['username']:
   1.174 +            username = p.dict['username'][:8]
   1.175 +        else:
   1.176 +            username = ""
   1.177 +        line = templ % (p.pid,
   1.178 +                        username,
   1.179 +                        p.dict['nice'],
   1.180 +                        bytes2human(getattr(p.dict['memory_info'], 'vms', 0)),
   1.181 +                        bytes2human(getattr(p.dict['memory_info'], 'rss', 0)),
   1.182 +                        p.dict['cpu_percent'],
   1.183 +                        p.dict['memory_percent'],
   1.184 +                        ctime,
   1.185 +                        p.dict['name'] or '',
   1.186 +                        )
   1.187 +        try:
   1.188 +            print_line(line)
   1.189 +        except curses.error:
   1.190 +            break
   1.191 +        win.refresh()
   1.192 +
   1.193 +
   1.194 +def main():
   1.195 +    try:
   1.196 +        interval = 0
   1.197 +        while 1:
   1.198 +            args = poll(interval)
   1.199 +            refresh_window(*args)
   1.200 +            interval = 1
   1.201 +    except (KeyboardInterrupt, SystemExit):
   1.202 +        pass
   1.203 +
   1.204 +if __name__ == '__main__':
   1.205 +    main()

mercurial