您可以通过在传输之前调用datetime.datetime.now()来获得传输开始的时间。在
您可以通过在传输之后再次调用它来获取传输结束的时间。在
如果你减去这些,你就得到了下载所花的时间。如果您使用的是datetime对象,这是一个timedelta。在
你可以通过传输后的文件stat来获得下载或上传的字节数。在
所以:bytespersec = bytestransfered / (endtime - starttime).totalseconds()
如果您想在传输仍在进行时获得速度,您不能使用简单的“一次性上载整个文件”命令,但几乎所有FTP库(包括stdlib的ftplib)都将具有回调驱动或屈服驱动的API,或者提供自己的文件类对象的方法,或者其他方法来“钩住”本地文件的读/写。所以,每次调用钩子时都可以进行完全相同的计算,使用当前时间和到目前为止的总字节数(可以跟踪这些字节数),而不是在末尾。在
如果你想这样,你的下一个问题可能是,“我如何完成百分比?”您可以在下载之前向服务器询问文件大小(通过您最喜欢的FTP库的包装器,在上传之前SIZE命令)和{}本地文件,然后每次调用钩子时,只需将到目前为止的字节数除以总大小。(您可能还想为不处理SIZE的服务器编写后备代码,方法是执行LIST并尝试解析两种最典型的格式。或者您的FTP库可能已经有办法做到这一点。)
根据您的示例代码,您几乎都是正确的,但有一个问题:
^{pr2}$
您只是在计算从开始将当前数据块写入磁盘的时间。如果您需要每个块的时间,请从一个块的末尾开始计算到下一个块的结束;如果您希望迄今为止的平均时间,则从整个进程的开始开始开始计数。不管是哪种方式,这意味着您需要在调用之间存储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和{},并且只在回调函数的末尾重置block_start_time。在
作为一个旁注:你永远不会close文件。这意味着不能保证最后一块数据会被刷新到磁盘上。它通常可以工作(至少在CPython中是这样),但偶尔会出现被截断的文件。总是close任何你的open,尤其是在写模式下,或者更好的是,使用with语句,如the tutorial所述。在
此外,隐藏异常的详细信息会使代码难以调试,最终用户也更难使用。例如,无论您的internet连接断开,远程文件丢失,或者您没有对本地文件的写入权限,这些都将显示为“错误”。至少打印Exception或其repr,如下所示:except Exception as e:
print "Error:", repr(e)