Python编写仿wget工具时计算MB/s下载速率的公式是否正确?
下载速率统计逻辑评估与优化方案
你当前的逻辑是计算从下载启动到当前时刻的整体平均下载速率,这个逻辑本身没有计算错误,在带宽稳定的场景下和实际速度匹配度很高,问题主要在场景适配性上:
- 短时间网络波动的时候,平均速率的变化会很滞后,没法实时反馈当前的实际下载速度
- 如果下载的文件很小,总下载耗时不足1秒的话,
time.time()-old的差值太小,会导致计算出来的速率数值误差极大
无需更换网络的多带宽验证方法
你不用换物理网络环境也能做不同带宽的验证:
- Linux 环境可以直接用
tc命令限制网卡带宽,比如执行tc qdisc add dev eth0 root tbf rate 1mbit burst 10k latency 70ms就能把网卡限速到1Mbps,测试完用tc qdisc del dev eth0 root恢复即可 - Windows 环境可以用系统组策略或者第三方限速工具给程序限制带宽,也能模拟不同网络环境
优化实现方案
推荐用滑动窗口统计最近N秒的平均速率,兼顾实时性和平滑性,比全周期平均的显示效果更符合用户感知:
import time from collections import deque print(f"Downloading: [{size/1048576:.2f}MB]{file_name}...") done = 0 old = time.time() # 初始化滑动窗口,保存最近1秒内的(时间戳, 下载字节数)记录 speed_window = deque() WINDOW_SECONDS = 1 # 窗口大小,数值越大速率显示越平滑,越小越灵敏 for chunk in r.iter_content(chunk_size=65536): f.write(chunk) chunk_len = len(chunk) done += chunk_len now = time.time() # 更新滑动窗口,移除过期记录 speed_window.append((now, chunk_len)) while speed_window and now - speed_window[0][0] > WINDOW_SECONDS: speed_window.popleft() # 计算速率,窗口数据不足时 fallback 到总平均 if len(speed_window) >= 1 and now - speed_window[0][0] > 0: window_total = sum(i[1] for i in speed_window) window_time = now - speed_window[0][0] mbps = f"{window_total / window_time / 1048576:.2f}" else: total_time = max(now - old, 0.1) mbps = f"{done / total_time / 1048576:.2f}" perc = done / size progress_bar = "=" * int(perc * 50) + " " * (50 - int(perc * 50)) print(f"[{progress_bar}][{mbps}Mb/s]{int(perc*100)}%", end="\r") f.close()
优化点说明
- 滑动窗口统计的速率更接近用户感知的「当前网速」,不会被前期的速度拉低/拉高显示值
- 替换了原来的字符串切片取前4位的写法,用格式化字符串保留2位小数,避免出现
10.2、102.这类异常显示格式 - 加了除零保护,避免刚开始下载时间差过小的时候计算报错
内容的提问来源于stack exchange,提问作者Topster_
相关产品推荐
相关产品推荐

