如何通过pysftp监控文件传输进度
我正在使用 Python 3.3.2 和 pysftp 来制作一个备份工具,这个工具可以把文件的副本存储到我网络上另一台电脑上。
我已经知道怎么用 pysftp 来传输这些文件了,不过我想看到传输的进度,比如每秒传输多少字节、完成了多少百分比、还剩多少时间,而不是只看到一个静态的打印信息,告诉我传输开始或结束。
我想要的效果可能是这样的(文件名:3.4MiB/s | 40%<#########=============> | 还剩 0:03:54)
编辑:如果我知道怎么让 pysftp 的 put 命令提供这些信息,我可能就能做一个进度条,这正是我想知道的。
编辑:经过一番查找,我觉得我在另一个问题中找到了答案:
6 个回答
这就是使用 rich 库的效果。
import pysftp
from rich.progress import Progress
with pysftp.Connection(host=None, username=None, password=None) as sftp:
file_to_download = '.'
with Progress() as progress:
task = progress.add_task(f"[red]Downloading {file_to_download} ...", total=None)
sftp.get(
file_to_download,
local_path,
callback=lambda so_far, total: progress.update(task, completed=so_far, total=total),
)
如果你想使用tqdm这个进度条:
from tqdm import tqdm
import pysftp
class Progressbar(tqdm):
def update_to(self, gathered: int, total: int):
self.total = total
self.update(gathered - self.n)
pb = Progressbar(
desc=f"downloading {filename}",
unit="ib",
unit_divisor=1 << 20, #MiB
unit_scale=True,
)
with pysftp.Connection(host, username, password) as sftp:
sftp.get(filename, callback=pb.update_to)
在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后在程序中使用这些数据。这个过程就像是从冰箱里拿食材,然后用这些食材做饭。
当我们说到“数据处理”,其实就是在说如何把这些食材(数据)整理好,准备好,才能做出美味的菜肴(程序的功能)。
有些时候,数据可能会有点乱,比如说冰箱里食材的种类太多,或者过期了,这时候我们就需要先把这些食材整理一下,挑选出新鲜的,才能开始做饭。
在编程中,我们也会遇到类似的情况,比如数据格式不对,或者缺少某些信息,这时候我们就需要用一些工具或者方法来清理和整理这些数据。
总之,数据处理就是让我们能更方便地使用数据,最终实现我们想要的功能,就像做饭一样,准备好食材才能做出好吃的菜。
import math, pysftp
with pysftp.Connection(host, username, password) as sftp:
sftp.get(remotepath, localpath, callback=lambda x,y: progressbar(x,y))
def progressbar(x, y):
''' progressbar for the pysftp
'''
bar_len = 60
filled_len = math.ceil(bar_len * x / float(y))
percents = math.ceil(100.0 * x / float(y))
bar = '=' * filled_len + '-' * (bar_len - filled_len)
filesize = f'{math.ceil(y/1024):,} KB' if y > 1024 else f'{y} byte'
sys.stdout.write(f'[{bar}] {percents}% {filesize}\r')
sys.stdout.flush()
[============================================================] 100% 4,342 KB
你可以创建一个函数,每当进度达到(比如说)10%时就打印一次转移的状态:
progressDict={}
progressEveryPercent=10
for i in range(0,101):
if i%progressEveryPercent==0:
progressDict[str(i)]=""
def printProgressDecimal(x,y):
if int(100*(int(x)/int(y))) % progressEveryPercent ==0 and progressDict[str(int(100*(int(x)/int(y))))]=="":
print("{}% ({} Transfered(B)/ {} Total File Size(B))".format(str("%.2f" %(100*(int(x)/int(y)))),x,y))
progressDict[str(int(100*(int(x)/int(y))))]="1"
然后你可以在你的获取或放置命令中这样调用这个函数:
sftp.get(eachFile,localpath=localDirectory+eachFile, callback=lambda x,y: printProgressDecimal(x,y))
一个示例输出是:
0.00% (32768 Transfered(B)/ 1108907068 Total File Size(B))
10.00% (110919680 Transfered(B)/ 1108907068 Total File Size(B))
20.00% (221806592 Transfered(B)/ 1108907068 Total File Size(B))
30.00% (332693504 Transfered(B)/ 1108907068 Total File Size(B))
40.00% (443580416 Transfered(B)/ 1108907068 Total File Size(B))
50.00% (554467328 Transfered(B)/ 1108907068 Total File Size(B))
60.00% (665354240 Transfered(B)/ 1108907068 Total File Size(B))
70.00% (776241152 Transfered(B)/ 1108907068 Total File Size(B))
80.00% (887128064 Transfered(B)/ 1108907068 Total File Size(B))
90.00% (998047744 Transfered(B)/ 1108907068 Total File Size(B))
100.00% (1108907068 Transfered(B)/ 1108907068 Total File Size(B))
在get和put方法中都有一个回调函数(可以查看官方的文档)
get(remotepath, localpath=None, callback=None, preserve_mtime=False)
回调函数的样子可能是这样的:
lambda x,y: print("{} transfered out of {}".format(x,y))