如何用Python计算互联网数据用量?psutil等工具适用性疑问
一、psutil是否合适?完全合适
psutil是跨平台的系统监控库,专门用于获取系统资源使用数据,其中就包含网络收发字节数的统计功能。它封装了底层系统调用,无需你处理复杂的系统细节,代码简洁且可靠性高,非常适合快速实现网络数据用量统计的需求。
具体使用方法
通过psutil.net_io_counters()可以获取网络接口的收发字节统计,计算不同时间点的差值就能得到某段时间内的数据用量:
import psutil import time def calculate_network_usage(monitor_interval=1): # 获取初始统计值 initial_stats = psutil.net_io_counters() start_sent = initial_stats.bytes_sent start_recv = initial_stats.bytes_recv time.sleep(monitor_interval) # 获取结束统计值 final_stats = psutil.net_io_counters() end_sent = final_stats.bytes_sent end_recv = final_stats.bytes_recv # 计算用量差值 sent_mb = (end_sent - start_sent) / 1024 / 1024 recv_mb = (end_recv - start_recv) / 1024 / 1024 return f"发送流量: {sent_mb:.2f} MB, 接收流量: {recv_mb:.2f} MB" # 示例:统计10秒内的网络用量 print(calculate_network_usage(10))
如果需要单独统计某块网卡(比如WiFi或以太网)的用量,可以给net_io_counters()传入pernic=True,然后指定对应网卡名称(Windows下如"以太网",Linux下如"eth0")。
二、用socket实现的可行性
socket是网络通信的底层API,可以实现,但工作量极大,不推荐。
原理是创建原始套接字捕获所有经过网卡的IP数据包,然后累加每个数据包的大小。但这种方式需要管理员权限,还要自行处理不同协议(TCP/UDP/ICMP等)的数据包解析,甚至要区分本地与互联网流量(避免统计局域网内传输数据),实现逻辑繁琐且容易出错,远不如psutil高效可靠。
仅做思路演示(代码不完整,无法直接用于生产):
import socket # 需管理员权限运行 raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) raw_socket.bind(("0.0.0.0", 0)) raw_socket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) raw_socket.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) total_traffic = 0 try: while True: packet = raw_socket.recvfrom(65565)[0] total_traffic += len(packet) print(f"累计流量: {total_traffic/1024/1024:.2f} MB") except KeyboardInterrupt: raw_socket.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) raw_socket.close()
该代码仅能捕获接收数据包,还需额外处理发送数据包,且无法区分公网/内网流量,实际使用需大量补充逻辑。
三、用Scapy实现的方案
Scapy是专门的数据包处理库,比socket更易用,可以实现精准的互联网数据用量统计,适合需要自定义过滤规则的场景。
原理是用Scapy的sniff功能捕获数据包,通过判断IP地址是否为公网地址,过滤出互联网流量并累加数据包大小。
示例代码:
from scapy.all import sniff, IP import ipaddress total_sent = 0 total_recv = 0 def is_public_ip(ip_str): try: ip = ipaddress.ip_address(ip_str) return not (ip.is_private or ip.is_loopback or ip.is_link_local) except ValueError: return False def process_packet(packet): global total_sent, total_recv if IP in packet: src_ip = packet[IP].src dst_ip = packet[IP].dst packet_size = len(packet) if is_public_ip(dst_ip): total_sent += packet_size if is_public_ip(src_ip): total_recv += packet_size print(f"累计发送: {total_sent/1024/1024:.2f} MB | 累计接收: {total_recv/1024/1024:.2f} MB") # 开始嗅探,需管理员权限 sniff(prn=process_packet, store=0)
这个方案可以精准区分公网与内网流量,但同样需要管理员权限,且嗅探过程会占用一定系统资源,适合有精细化统计需求的场景。
总结
- 优先选择psutil:简单、跨平台、无需特殊权限(多数系统),适合快速实现通用网络用量统计。
- Scapy适合精细化场景:需要区分公网/内网流量、自定义过滤规则时使用,但依赖管理员权限。
- socket不推荐:底层实现繁琐,开发成本高,除非有特殊底层需求,否则没必要使用。
内容的提问来源于stack exchange,提问作者Esra Issam

