我需要使用ftp.retrbinary命令确定FTP期间客户端PC的下载或上传速度。如何确定每个块下载的速度(以Mbps为单位)?
def download_file(block):
global sizeWritten
start_time = time.mktime(time.localtime())
file.write(block)
end_time = time.mktime(time.localtime())
os.system('CLS')
sizeWritten += len(block)
percentComplete = sizeWritten / totalSize
percentComplete = round((percentComplete*100),1)
# if totalTime != 0:
# throughput=sizeWritten/totalTime
# throughput=throughput/(1024*1024)
# throughput=throughput*8
# throughput=round(throughput,3)
# print(throughput, "MBPS")
print (percentComplete, "% complete")
try:
file = open('100file.zip', "wb")
print("File opened")
ftp.retrbinary("RETR " + '100file.zip' ,download_file)
print("Download Successful!")
except:
print("Error")
答案 0 :(得分:0)
您可以通过在转移之前致电(例如datetime.datetime.now()
)来获取转移开始的时间。
您可以通过在转移后再次呼叫来获取转移结束的时间。
如果你减去这些,你会得到下载的时间。如果您使用的是datetime
个对象,则为timedelta
。
您可以通过例如传输后stat
文件获取下载或上传的字节数。
所以:
bytespersec = bytestransfered / (endtime - starttime).totalseconds()
如果你想在传输仍在进行时获得的速度,你不能使用简单的“一次性上传整个文件”命令,但几乎任何FTP库 - 包括stdlib的ftplib
- 将具有回调驱动或产量驱动的API,或者提供自己的类文件对象的方法,或者某种其他方式来“挂钩”本地文件的读/写。因此,每次调用钩子时,您可以使用当前时间和到目前为止的总字节数(您可以跟踪)而不是在结束时执行完全相同的计算。
如果你想要那样,你的下一个问题可能是,“如何完成%?”您可以在下载之前询问服务器的文件大小(通过您最喜欢的FTP库的SIZE
命令包装器),然后在上传之前stat
本地文件,然后每次调用挂钩时,到目前为止,只按总大小划分字节数。 (您可能还想通过执行SIZE
并尝试解析两种最典型的格式来为不处理LIST
的服务器编写回退代码。或者您的FTP库可能已经有办法这一点。)
根据你的示例代码,你几乎把事情做对了,但是有一个问题:
def download_file(block):
global sizeWritten
start_time = time.mktime(time.localtime())
file.write(block)
end_time = time.mktime(time.localtime())
# ...
您只是计算从开始将当前数据块写入磁盘后的时间。如果你想要每个块的时间,从一个块的末尾到下一个块的末尾计数;如果你想要到目前为止的平均时间,从整个过程的开始算起。无论哪种方式,这意味着您需要在调用之间存储start_time
的地方。由于您已经在使用sizeWritten
的全局变量,因此您可以在此处执行相同操作:
def download_file(block):
global sizeWritten
global start_time
file.write(block)
end_time = time.mktime(time.localtime())
# ...
try:
file = open('100file.zip', "wb")
sizeWritten = 0
start_time = time.mktime(time.localtime())
如果你想要时间/阻止,只需在回调函数的末尾添加另一个start_time = time.mktime(time.localtime())
。如果您想要两者,只需创建两个变量block_start_time
和overall_start_time
,并仅在回调函数结束时重置block_start_time
。
作为旁注:您永远不会close
该文件。这意味着无法保证最后一块数据将被刷新到磁盘。它通常工作(至少在CPython中),但偶尔你会得到截断的文件。永远close
您open
的任何内容,特别是在写入模式下,或者更好的是,使用with
语句,如the tutorial中所述。
此外,隐藏异常细节会使您的代码难以调试,并且最终用户难以使用。例如,无论您的Internet连接是否已关闭,远程文件是否丢失,或者您没有对本地文件的写入权限,它们都将显示为“错误”。至少打印Exception
或其repr
,如下所示:
except Exception as e:
print "Error:", repr(e)