【问题标题】:Determine Download and Upload Speed of Client Computer Python [closed]确定客户端计算机 Python 的下载和上传速度 [关闭]
【发布时间】:2014-02-04 12:58:54
【问题描述】:

我需要使用 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")

【问题讨论】:

    标签: python upload download client


    【解决方案1】:

    您可以在转帐前拨打电话,例如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_timeoverall_start_time,并且只在回调函数结束时重置 block_start_time


    附带说明:您永远不会close 文件。这意味着不能保证最后一个数据块会被刷新到磁盘。它通常可以工作(至少在 CPython 中是这样),但有时你会得到截断的文件。总是close 任何你open 的东西,尤其是在写模式下——或者更好的是,使用with 语句,如the tutorial 中所述。

    此外,隐藏异常的详细信息会使您的代码难以调试,最终用户也更难使用。例如,无论您的 Internet 连接断开、远程文件丢失,还是您没有本地文件的写入权限,都只会显示为“错误”。至少打印Exception 或其repr,如下所示:

    except Exception as e:
        print "Error:", repr(e)
    

    【讨论】:

    • 这是我一直遵循的路线,谢谢!但是,对于回调函数,我找不到放置开始时间和结束时间的地方。我假设我会将它们放在 file.write(block) 之前和之后,但结果却是相同的值。块实际上在哪里开始和结束写作?
    • @ChanceB:您需要将整个过程的开始时间存储在回调之外的某个位置——实例属性、闭包变量或全局变量。现在您已将代码编辑到问题中,我可以将示例编辑到我的答案中。
    • @abarnert 我在这里有类似的问题,但我正在尝试监控上传 ftp 速度,然后计算平均上传速度。我遇到了一个问题,我没有看到与使用其他 ftp 软件相同的上传速度。
    • 基于这个答案和我发现的其他信息,我编写了这些 python 脚本来测量网络延迟和下载/上传带宽,进行多次测试并将结果保存到 csv 文件,以及一些统计信息(最大值、最小值、 avg、中值速度和标准偏差),可以作为示例使用或检查。 github.com/juanluisbaptiste/network-tests
    猜你喜欢
    • 2011-05-16
    • 2023-03-29
    • 1970-01-01
    • 2011-06-02
    • 2015-09-16
    • 1970-01-01
    • 2016-12-06
    • 2018-03-12
    • 1970-01-01
    相关资源
    最近更新 更多