Python获取上传/下载速度
我想在我的电脑上监控上传和下载的速度。有一个叫做conky的程序已经可以做到这一点,下面是它的配置文件中的内容:
Connection quality: $alignr ${wireless_link_qual_perc wlan0}%
${downspeedgraph wlan0}
DLS:${downspeed wlan0} kb/s $alignr total: ${totaldown wlan0}
它可以在我浏览的时候,几乎实时地显示我的网速。我想用python也能获取到同样的信息。
4 个回答
你可以做一些不太正规的事情,比如运行 conky -i 1
并解析它的输出:
import subprocess
conky=subprocess.check_output("conky -i 1", shell=True)
lines=conky.splitlines()
print lines[11].split()[1::3]
这样会得到:
['1234B', '5678B']
我的配置文件看起来是这样的:
${scroll 16 $nodename - $sysname $kernel on $machine | }
Uptime: $uptime
Frequency (in MHz): $freq
Frequency (in GHz): $freq_g
RAM Usage: $mem/$memmax - $memperc% ${membar 4}
Swap Usage: $swap/$swapmax - $swapperc% ${swapbar 4}
CPU Usage: $cpu% ${cpubar 4}
Processes: $processes Running: $running_processes
File systems:
/ ${fs_used /}/${fs_size /} ${fs_bar 6 /}
Networking:
Up: ${upspeed eth0} - Down: ${downspeed eth0}
Name PID CPU% MEM%
${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1}
${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2}
${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3}
${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4}
为了获取特定接口的统计信息,之前提到的方法都可以很好地工作。
我这次想给你提供一个关于你第二个请求的解决方案:
知道哪个程序在使用带宽也是非常有帮助的,但到目前为止,我还没有看到可以做到这一点的工具。
正如之前提到的,nethogs可以打印出与进程相关的统计信息。根据我的了解,在/proc
下没有简单的方法可以获取这些值,所以我会解释一下nethogs是如何做到的。
以一个进程的PID为例,nethogs首先会获取该进程打开的所有套接字的列表,这些信息存储在/proc/PID/fd
中:
➜ ~ [1] at 23:59:31 [Sat 15] $ ls -la /proc/21841/fd
total 0
dr-x------ 2 marco marco 0 Nov 15 23:41 .
dr-xr-xr-x 8 marco marco 0 Nov 15 23:41 ..
lrwx------ 1 marco marco 64 Nov 15 23:42 0 -> /dev/pts/15
l-wx------ 1 marco marco 64 Nov 15 23:42 1 -> /dev/null
lrwx------ 1 marco marco 64 Nov 15 23:41 2 -> /dev/pts/15
lrwx------ 1 marco marco 64 Nov 15 23:42 4 -> socket:[177472]
这里我们只有一个套接字,177472是它的inode编号。我们会在这里找到各种类型的套接字:TCPv4、TCPv6、UDP、netlink。在这个例子中,我只考虑TCPv4。
一旦收集到所有的inode编号,每个套接字会被分配一个唯一的标识符,也就是(IP_SRC, PORT_SRC, IP_DEST, PORT_DEST)
。当然,和PID的配对也会被存储。这个元组(IP_SRC, PORT_SRC, IP_DEST, PORT_DEST)
可以通过读取/proc/net/tcp
(针对TCPv4)来获取。在这个情况下:
➜ ~ [1] at 0:06:05 [Sun 16] $ cat /proc/net/tcp | grep 177472
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
38: 1D00A8C0:1F90 0400A8C0:A093 01 00000000:00000000 00:00000000 00000000 1000 0 177472 1 f6fae080 21 4 0 10 5
地址以IP:PORT的形式表示,IP用一个4字节的LE数字表示。然后你可以构建一个key->value
结构,其中key是(IP_SRC, PORT_SRC, IP_DEST, PORT_DEST)
,而value则是PID。
此时,nethogs会使用libpcap捕获所有的网络流量。当它检测到一个TCP数据包时,它会尝试将元组(IP_SRC_PACKET, PORT_SRC_PACKET, IP_DEST_PACKET, PORT_DEST_PACKET)
与表中的所有连接进行匹配。当然,它还需要尝试交换SRC和DEST,因为数据包可能是进入的(DL)或出去的(UL)。如果匹配到一个连接,它会获取该连接所属进程的PID,并将TCP负载的大小加到TX或RX计数器中。随着每个捕获的数据包更新字节数,可以轻松计算出每个进程的传输速度。
理论上,这可以用python和pypcap来实现,尽管需要一些工作。我尝试实现了一些东西,但速度非常慢,还需要更多的工作才能使用。我只监控了一个PID,只有一个连接,没有更新连接表,但超过3MB/s时,我的脚本无法跟上网络流量。
如你所见,这并不是一件简单的事。解析一个已经存在的工具的输出可能会导致更好的解决方案,并且可以节省你很多工作。
我建议你看看这个psutil模块,它是用来在Python中处理系统和进程信息的。
下面是一段简单的代码,可以显示自从你开机以来发送的字节数:
import psutil
iostat = psutil.net_io_counters(pernic=False)
print iostat[0] #upload only
你可以很容易地扩展这段代码,让它在固定的时间间隔内获取这个值,然后比较这两个值,从而计算出在这段时间内发送和接收的字节数。
你可以根据设备的接收字节数(rx_bytes)和发送字节数(tx_bytes)来自己计算速度,并在一段时间内不断获取这些值。
下面是我用Python 3简单拼凑出来的一个解决方案。
#!/usr/bin/python3
import time
def get_bytes(t, iface='wlan0'):
with open('/sys/class/net/' + iface + '/statistics/' + t + '_bytes', 'r') as f:
data = f.read();
return int(data)
if __name__ == '__main__':
(tx_prev, rx_prev) = (0, 0)
while(True):
tx = get_bytes('tx')
rx = get_bytes('rx')
if tx_prev > 0:
tx_speed = tx - tx_prev
print('TX: ', tx_speed, 'bps')
if rx_prev > 0:
rx_speed = rx - rx_prev
print('RX: ', rx_speed, 'bps')
time.sleep(1)
tx_prev = tx
rx_prev = rx