Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 #!/usr/bin/env python
2 #
3 # $Id: iotop.py 1160 2011-10-14 18:50:36Z g.rodola@gmail.com $
4 #
5 # Copyright (c) 2009, 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.
9 """
10 Shows real-time network statistics.
12 Author: Giampaolo Rodola' <g.rodola@gmail.com>
13 """
15 import sys
16 import os
17 if os.name != 'posix':
18 sys.exit('platform not supported')
19 import curses
20 import atexit
21 import time
23 import psutil
26 # --- curses stuff
27 def tear_down():
28 win.keypad(0)
29 curses.nocbreak()
30 curses.echo()
31 curses.endwin()
33 win = curses.initscr()
34 atexit.register(tear_down)
35 curses.endwin()
36 lineno = 0
38 def print_line(line, highlight=False):
39 """A thin wrapper around curses's addstr()."""
40 global lineno
41 try:
42 if highlight:
43 line += " " * (win.getmaxyx()[1] - len(line))
44 win.addstr(lineno, 0, line, curses.A_REVERSE)
45 else:
46 win.addstr(lineno, 0, line, 0)
47 except curses.error:
48 lineno = 0
49 win.refresh()
50 raise
51 else:
52 lineno += 1
53 # --- curses stuff
56 def bytes2human(n):
57 """
58 >>> bytes2human(10000)
59 '9.8 K'
60 >>> bytes2human(100001221)
61 '95.4 M'
62 """
63 symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
64 prefix = {}
65 for i, s in enumerate(symbols):
66 prefix[s] = 1 << (i+1)*10
67 for s in reversed(symbols):
68 if n >= prefix[s]:
69 value = float(n) / prefix[s]
70 return '%.2f %s' % (value, s)
71 return '%.2f B' % (n)
73 def poll(interval):
74 """Retrieve raw stats within an interval window."""
75 tot_before = psutil.net_io_counters()
76 pnic_before = psutil.net_io_counters(pernic=True)
77 # sleep some time
78 time.sleep(interval)
79 tot_after = psutil.net_io_counters()
80 pnic_after = psutil.net_io_counters(pernic=True)
81 return (tot_before, tot_after, pnic_before, pnic_after)
84 def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
85 """Print stats on screen."""
86 global lineno
88 # totals
89 print_line("total bytes: sent: %-10s received: %s" \
90 % (bytes2human(tot_after.bytes_sent),
91 bytes2human(tot_after.bytes_recv))
92 )
93 print_line("total packets: sent: %-10s received: %s" \
94 % (tot_after.packets_sent, tot_after.packets_recv)
95 )
98 # per-network interface details: let's sort network interfaces so
99 # that the ones which generated more traffic are shown first
100 print_line("")
101 nic_names = list(pnic_after.keys())
102 nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True)
103 for name in nic_names:
104 stats_before = pnic_before[name]
105 stats_after = pnic_after[name]
106 templ = "%-15s %15s %15s"
107 print_line(templ % (name, "TOTAL", "PER-SEC"), highlight=True)
108 print_line(templ % (
109 "bytes-sent",
110 bytes2human(stats_after.bytes_sent),
111 bytes2human(stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
112 ))
113 print_line(templ % (
114 "bytes-recv",
115 bytes2human(stats_after.bytes_recv),
116 bytes2human(stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
117 ))
118 print_line(templ % (
119 "pkts-sent",
120 stats_after.packets_sent,
121 stats_after.packets_sent - stats_before.packets_sent,
122 ))
123 print_line(templ % (
124 "pkts-recv",
125 stats_after.packets_recv,
126 stats_after.packets_recv - stats_before.packets_recv,
127 ))
128 print_line("")
129 win.refresh()
130 lineno = 0
133 def main():
134 try:
135 interval = 0
136 while 1:
137 args = poll(interval)
138 refresh_window(*args)
139 interval = 1
140 except (KeyboardInterrupt, SystemExit):
141 pass
143 if __name__ == '__main__':
144 main()