如何对paramiko-sftp进行流量限速?能否实现sftp命令-l参数的同等效果?
实现paramiko-sftp限速的方案
可以实现和sftp -l参数完全一致的限速效果,核心思路是手动控制单位时间内的文件传输字节数,不需要依赖paramiko内置支持。
sftp命令的-l参数单位为Kbps(千比特每秒),实现时只需把速度值转换为每秒允许传输的字节数,在文件分块读写时补充等待逻辑即可,具体实现代码如下:
1. 限速工具类实现
import time import paramiko class BandwidthLimiter: def __init__(self, max_speed_kbps): # 将Kbps转换为字节每秒,1字节=8比特 self.max_bytes_per_sec = (max_speed_kbps * 1024) / 8 self.last_calc_time = time.time() self.transferred_bytes = 0 def throttle(self, bytes_count): self.transferred_bytes += bytes_count current_time = time.time() elapsed = current_time - self.last_calc_time # 每满1秒计算一次速度,超出限制则休眠补偿 if elapsed >= 1: expected_time_cost = self.transferred_bytes / self.max_bytes_per_sec if expected_time_cost > elapsed: time.sleep(expected_time_cost - elapsed) # 重置统计数据 self.transferred_bytes = 0 self.last_calc_time = time.time()
2. 带限速的文件上传示例
# 示例配置:限速1024Kbps,等同于sftp命令 -l 1024的效果 limit_kbps = 1024 limiter = BandwidthLimiter(limit_kbps) # 建立SSH和SFTP连接,和常规用法一致 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname="目标主机IP", port=22, username="用户名", password="密码") sftp = ssh.open_sftp() # 分块传输文件,每传一块调用一次限速逻辑 local_path = "/本地文件路径" remote_path = "/远程服务器存储路径" # 块大小建议设置为16~64KB,兼顾传输效率和限速精度 block_size = 32 * 1024 with open(local_path, "rb") as f_local, sftp.open(remote_path, "wb") as f_remote: while True: block_data = f_local.read(block_size) if not block_data: break f_remote.write(block_data) limiter.throttle(len(block_data)) # 关闭连接 sftp.close() ssh.close()
3. 下载文件限速调整
如果需要限速下载,只需把读写逻辑反过来:从远程sftp文件对象读块,写入本地文件,每次读完块后调用limiter.throttle方法即可。
注意事项
- 块大小不要设置过大,否则会出现速度跳变、限速精度下降的问题
- 该实现的限速误差在5%以内,和原生sftp的
-l参数效果基本一致 - 如果需要同时限制上传和下载速度,分别实例化两个
BandwidthLimiter对象单独控制即可
内容的提问来源于stack exchange,提问作者Teruhisa Abe
相关产品推荐
相关产品推荐

