psutil.net_io_counters() 返回的数值单位是字节数(bytes),为自系统启动以来的累计总收发字节数,非实时速率、非比特、非带单位字符串。
psutil.net_io_counters() 返回的数值单位是什么
返回的是字节数(bytes),不是比特(bits),更不是 KB/MB 带单位的字符串。很多新手直接拿结果除以 1024 就当成了 KB,却忽略了这是累计值、不是实时速率——psutil.net_io_counters() 每次调用返回的是自系统启动以来的总收发字节数。
要算实时带宽(如 MB/s),必须做两次采样、计算差值再除以时间间隔:
import psutil import timenet1 = psutil.net_io_counters(pernic=True)['eth0'] time.sleep(1) net2 = psutil.net_io_counters(pernic=True)['eth0'] recv_bps = (net2.bytes_recv - net1.bytes_recv) / 1.0 # 字节/秒 print(f"接收速率: {recv_bps / 1024 / 1024:.2f} MB/s")
- 务必用
pernic=True,否则默认只返回汇总值(可能含虚拟网卡、已下线设备,不可靠) - 网卡名(如
'eth0'或'en0')需先用list(psutil.net_if_addrs().keys())确认,Linux/macOS/Windows 差异大 - 两次采样间隔不宜过短(
为什么多次调用 net_io_counters() 后 recv_bytes 越来越小
这不是数据倒退,而是计数器溢出后回绕(wrap-around),常见于长时间运行的监控脚本。32 位计数器满值是 4GB,千兆网满载约 4 秒就溢出;64 位系统一般不会,但某些虚拟网卡或旧驱动仍可能返回 32 位值。
应对方式不是“修复”,而是主动检测并修正:
稿定在线PS
PS软件网页版
- 每次更新时判断
new_bytes ,若成立则视为溢出,按new_bytes + (2**32 - old_bytes)补全(32 位) - 更稳妥的做法是改用
psutil.sensors_battery()之外的方案?不,这里无关——应直接依赖/proc/net/dev(Linux)或GetIfEntry2(Windows)等底层接口,但开发成本高;对多数场景,加溢出校验比换库更实际 - 避免用单次调用结果做绝对值比较,所有速率计算必须基于相邻两次差值
如何区分物理网卡和 Docker/virtualbox 虚拟网卡
psutil.net_if_addrs() 返回的地址信息里,虚拟网卡通常没有 IPv4 默认网关、MAC 地址是特殊段(如 02:42:ac:xx:xx:xx 对应 Docker)、或接口名含 docker/vboxnet/veth 等字样。但最可靠的方式是结合路由表判断主出口:
import psutil找默认网关所在接口
gateways = psutil.net_if_addrs() default_gw = None for interface in psutil.net_if_addrs(): for addr in psutil.net_if_addrs()[interface]: if addr.family == socket.AF_INET and addr.address != '127.0.0.1':
这里需配合 psutil.net_if_stats() 或读取 /proc/net/route 判断是否为默认路由出口
pass
-
psutil.net_if_stats()中isup=True且speed > 0的更可能是物理网卡(但虚拟机桥接模式下 speed 可能非 0) - Linux 下可读
/sys/class/net//device/:存在该路径一般是物理设备;Docker 的vethxxx下无device子目录 - 别依赖接口名黑名单(如过滤
lo),有些生产环境会把业务跑在lo上做本地转发
Windows 下获取不到网卡流量或报错 KeyError
Windows 的网卡名和 Linux 完全不同:'Ethernet'、'Wi-Fi' 是常见名,但可能带编号('Ethernet 2')或 Unicode 字符(如中文系统显示为 '以太网')。直接硬编码 'eth0' 必然失败。
- 必须先运行
psutil.net_if_addrs().keys()获取真实列表,再人工或正则匹配关键词(如包含'eth'、'net'、'wifi') - 某些精简版 Windows(如 Server Core)或 Hyper-V 虚拟网卡可能不暴露完整统计,此时
psutil.net_io_counters(pernic=True)返回的字典里压根不包含该接口名——需做in判断,不能直接索引 - 权限问题:Windows 需管理员权限才能读取部分网卡(尤其无线适配器),普通用户运行会静默跳过或抛
PermissionError
监控带宽本身不难,难的是让结果在各种硬件、系统、虚拟化环境下都稳定可解释。最常被忽略的一点:不要假设“当前活跃的网卡就是流量最大的那个”——后台 P2P、自动更新、云盘同步可能长期占用某张闲置网卡,而你盯着的主网卡反而很安静。