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()