如何在Paramiko文件传输中计算剩余传输时间?
关于Paramiko文件传输添加剩余时间显示的解决方案
嘿,我来帮你搞定这个问题!首先明确一点:Paramiko本身并没有内置的模块来直接提供传输时间戳或计算剩余传输时间,不过我们可以自己手动实现这个功能,思路其实很清晰。
实现思路
要计算剩余传输时间,我们需要跟踪三个关键数据:
- 传输开始的时间点
- 实时的已传输数据量
- 基于历史传输数据计算的实时传输速度
有了这些数据,就可以用「剩余数据量 ÷ 实时传输速度」得到剩余时间,再把秒数格式化为HH:MM:SS的样式即可。
修改后的完整代码
我基于你现有的代码做了扩展,添加了剩余时间计算的逻辑:
import time import sys class YourSFTPClass: def __init__(self): self.client = None # 这里替换成你初始化Paramiko SSHClient的代码 # 新增用于跟踪传输状态的变量 self.start_time = None self.last_sent_bytes = 0 self.last_update_time = None def send_file(self, source, destination): # 初始化传输开始时间 self.start_time = time.time() self.last_sent_bytes = 0 self.last_update_time = self.start_time # 启动SFTP传输 self.client.open_sftp().put(source, destination, self.upload_status) def upload_status(self, sent, size): # 转换数据单位为MB total_mb = round(size / 1000000, 1) sent_mb = round(sent / 1000000, 1) remaining_mb = round((size - sent) / 1000000, 1) # 计算实时传输速度(用最近一次回调的增量,避免初始波动) current_time = time.time() bytes_delta = sent - self.last_sent_bytes time_delta = current_time - self.last_update_time if time_delta > 0 and bytes_delta > 0: # 计算MB/s的速度 speed_mb_per_sec = (bytes_delta / 1000000) / time_delta else: # 初始阶段或无数据传输时,速度设为0 speed_mb_per_sec = 0.0 # 更新上次记录的状态 self.last_sent_bytes = sent self.last_update_time = current_time # 计算剩余时间 if speed_mb_per_sec > 0: remaining_sec = (size - sent) / 1000000 / speed_mb_per_sec else: remaining_sec = 0 # 或者改为显示"Calculating..." # 格式化剩余时间为HH:MM:SS hours = int(remaining_sec // 3600) minutes = int((remaining_sec % 3600) // 60) seconds = int(remaining_sec % 60) remaining_time_str = f"{hours:02d}:{minutes:02d}:{seconds:02d}" # 输出状态行(覆盖当前行) status_output = ( f"Total size:{total_mb} MB|Sent:{sent_mb} MB|Remaining:{remaining_mb} MB|" f"Time remaining:{remaining_time_str}" ) sys.stdout.write(status_output) sys.stdout.write('\r') sys.stdout.flush() # 确保输出立即刷新到控制台
关键细节说明
- 避免除以0错误:当传输刚开始(还没有数据增量)或者传输暂停时,我们会把速度设为0,此时剩余时间显示为
00:00:00,你也可以改成显示Calculating...来提升用户体验。 - 实时速度计算:用两次回调之间的字节增量和时间增量计算速度,比用总传输量除以总时间更准确,能反映当前的真实传输速率。
- 时间格式化:通过整数运算把剩余秒数转换成小时、分钟、秒,并用
02d格式确保两位数的显示(比如1分钟会显示为01)。 - 强制刷新输出:添加
sys.stdout.flush()确保状态行能实时更新,避免因为缓冲区导致的显示延迟。
内容的提问来源于stack exchange,提问作者Ravish Mallya
相关产品推荐
相关产品推荐

